I'm trying to make a transposer in JavaScript..
Give it a key and a scale/mode and it will generate it for you
For instance
C Lydian (WWWHWWH) is C D E F# G A B
C Aeolian (WHWWHWW) is C D Eb F G Ab Bb
I cannot for the life of me figure out how to accomplish this.
Thoughts?
>inb4 SICP
make a list of items
for a given transposition, move +|- a given position
print results
Name:
Anonymous2010-06-10 13:40
>>4 I thought about that, but then what do for flats and sharps?
In music theory, you can't use sharps and flats in the same key, you must use one or the other
Also, that doesn't help me generate modes that would only change the key
Name:
Anonymous2010-06-10 13:46
>>5
You have to state the rule concerning which go into a particular key.
Clearly you haven't read your SICP today.
Have two lists: one octave using sharps and one using flats
Then, after using your rule [or prompting the user how the result should be expressed] perform the function on the appropriate octave.
Name:
Anonymous2010-06-10 13:51
Basically you can't have a neutral, sharp or flat from the same note in the same scale ...so the C Lydian example has to have F# because it can't have Gb because it has a G in already
OH GOOD JOB AND THANKS FOR CONTRIBUTING SOMETHING NEW
Name:
Anonymous2010-06-10 14:01
>>6
This seems inelegant to me. >>7 has it right
For instance, while G# Aeolian (G# A# B C# D# E F#) is valid
G# Lydian (G# A# C D D# F G) is wrong, it's actually Ab (Ab Bb C D Eb F G) because you can't use D and D#
Please cut me some slack, I've been self taught at everything I do in life, I don't want to go to college and put myself in thousands and thousands in debt for something I can teach myself. Just a few helpful pointers is all I'm asking for.
Name:
Anonymous2010-06-10 14:05
I don't want to go to college and put myself in thousands and thousands in debt
lol amerikkka
Name:
Anonymous2010-06-10 14:14
Two enums: one with sharps, one with flats.
Say somewhere that G# Lydian prefers the 'flats' enumeration.
Do this for all scales
Name:
Anonymous2010-06-10 14:20
>>11
Again, inelegant
That would require an exception for nearly every scale
I might as well hard-code every scale and just parse that
I should only need two arrays, a list of keys 0-12 (C, C#/Db, etc) the name and formula of every scale
Every thing else should be generated by code
>>11 is what I said in >>6. I added the idea of prompting to save you from having to go in and specify which is which in case you're too lazy to implement it or (more likely) not clever enough to find an elegant solution.
Just map it out and transpose it.
Look at the resultant string
If it contains a conflicting natural and accidental, switch to the other list.
>>12
Okay, how about something like keys = { "C", "C#/Db", "D", ... }
scales = { "Major": "2212221", ... } // how many semitones difference (i.e. 2 = whole, 1 = half)
function thingy(offset, scale) {
to_print = '#'; // start off printing the sharps by default
for (i = 0, key = offset; i++, key += scales[scale][i]; i < scales[scale].length) { // or something to that effect, also wrap around keys[] with key % 12 somewhere
if (keys[key] like keys[key+1]) { if they both contain the same letter, you're printing the wrong ones
to_print = 'b';
} // if (a like b) will only happen once
add_to_print_queue (keys[key]);
}
print_the_queue();
}
I dunno, I made it up as I went along. But something like that.
Name:
Anonymous2010-06-10 14:49
I've just knocked something up in C to do this. Not well tested.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int maj[7] = {2,2,1,2,2,2,1};
int min[7] = {2,1,2,2,1,2,2};
char *N = "ABCDEFGABCDEFG";
void printscale(char k, char a, int s[7],char *d) {
int i;
char *p = strchr(N,k);
printf("%s: %c%c",d,k,a);
for(i=0;i<7;i++) {
p++;
switch(a) {
case 'b': if(s[i]==3) a = ' '; break;
case ' ': if(s[i]==1) a = 'b'; break;
case '#': if(s[i]==1) a = ' '; break;
}
if(*p=='C'||*p=='F') {
switch(a) {
case 'b': a = ' '; break;
case ' ': a = '#'; break;
case '#': a = 'b'; p++; break;
}
}
printf(" %c%c",*p,a);
}
printf("\n");
}
int main(int argc, char **argv) {
char k='C',a=' ';
if(argv[1]) {
k = argv[1][0];
if(islower(k))
k = toupper(k);
if(!strchr(N,k)) {
printf("error: invalid key\n");
return 1;
}
a = argv[1][1];
if(!(a==0||a=='#'||a=='b')) {
printf("error: invalid key\n");
return 1;
} else if(a==0)
a = ' ';
}
>>17 scales = { "Major": "2212221",
This is not what strings are for. Strings are for text, they are not for structured data. Fuck, we knew this in the 60s. Fucking web programmers
>>20
Numbers aren't a structured data type either. This is what an array is for. [2,2,1,2,2,2,1] displays your intent much better, and you get to use all the array operations too. >>18 had the right idea.
>>22
Put it this way, if you need an integer you use an integer. You do not use "1", this much is obvious to any newbie coder. Yet the corollary, that when you need a collection of integers, you use a collection of integers seems less obvious to you? The one integer solution was even worse, as you would need to use binary operations to get the number out instead of whatever string->integer function javascript provides.
>>23
Put it this way. It was intended to be pseudocode, the fact that it looked like javascript was partially coincidence and partially because >>1 wants it like that. Also >>20 was taking your piss, as they say, because you called me a "web programmer" even though javascript is far from my favourite language. So I went the other way. Thanks, by the way, because this is now entirely devoid of humour.
I've been self taught at everything I do in life I don't want to go to college . . . for something I can teach myself. Just a few helpful pointers is all I'm asking for. Just a few helpful pointers is all I'm asking for. Just a few helpful pointers is all I'm asking for.
>>1
You know, an OP saying ``inb4'' is quite a stupid thing. This is because the OP will be before everything in his thread because he is the first poster!