Created
November 1, 2011 23:59
-
-
Save cemevin/1332328 to your computer and use it in GitHub Desktop.
Synthesizer in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <fstream> | |
| #include <iostream> | |
| #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) | |
| #define MAX(X,Y) ((X) < (Y) ? (Y) : (X)) | |
| #define SAMPLE (44100.0) | |
| #define BUFFER_LENGTH ((int)(SAMPLE)*10) | |
| #define C4 (int)(SAMPLE/261.63) | |
| #define D4 (int)(SAMPLE/293.66) | |
| #define E4 (int)(SAMPLE/329.63) | |
| #define F4 (int)(SAMPLE/349.23) | |
| #define G4 (int)(SAMPLE/392.0) | |
| #define A4 (int)(SAMPLE/440.0) | |
| #define B4 (int)(SAMPLE/493.88) | |
| #define C5 C4/2 | |
| #define KEY_STATE_PRESSED 0 | |
| #define KEY_STATE_RELEASED 1 | |
| #define ENVELOPE_STATE_STOP 0 | |
| #define ENVELOPE_STATE_ATTACK 1 | |
| #define ENVELOPE_STATE_DECAY 2 | |
| #define ENVELOPE_STATE_SUSTAIN 3 | |
| #define ENVELOPE_STATE_RELEASE 4 | |
| using namespace std; | |
| /********** variables **********/ | |
| int ENVELOPE_ATTACK = (int)SAMPLE/2; | |
| int ENVELOPE_DECAY = 1; | |
| float ENVELOPE_SUSTAIN = 0.; | |
| int ENVELOPE_RELEASE = 1; | |
| float VOLUME = 0.; | |
| char KEY_STATE = KEY_STATE_RELEASED; | |
| char ENVELOPE_STATE = ENVELOPE_STATE_STOP; | |
| /********** END variables **********/ | |
| void setEnvelopeSettings(int attack, int decay, float sustain, int release, float volume = 0., char keystate = KEY_STATE_RELEASED, char envelopestate = ENVELOPE_STATE_STOP){ | |
| ENVELOPE_ATTACK = attack; | |
| ENVELOPE_DECAY = decay; | |
| ENVELOPE_SUSTAIN = sustain; | |
| ENVELOPE_RELEASE = release; | |
| VOLUME = volume; | |
| KEY_STATE = keystate; | |
| ENVELOPE_STATE = envelopestate; | |
| } | |
| void osc(int note, unsigned char * buffer, int length){ | |
| int note2 = note/2; | |
| for(int i=0; i<length; i++) | |
| { | |
| if(i%note < note2){ | |
| buffer[i] = 0xff; | |
| } | |
| else{ | |
| buffer[i] = 0x00; | |
| } | |
| } | |
| } | |
| void flush_buffer(ofstream & of, unsigned char * buffer, int length){ | |
| for(int j=0;j<length;j++){ | |
| of<<(unsigned char)buffer[j]; | |
| } | |
| } | |
| float envelope_stop(); | |
| float envelope_attack(); | |
| float envelope_decay(); | |
| float envelope_sustain(); | |
| float envelope_release(); | |
| float envelope(); | |
| int main() | |
| { | |
| unsigned char buffer[BUFFER_LENGTH]; //10 second buffer | |
| int time = 0; | |
| int notes[]={C4,D4,E4,F4,G4,A4,B4,C5,C5,B4,A4,G4,F4,E4,D4,C4}; | |
| ofstream of("output1.raw"); | |
| /*for(int i=0;i<1;i++){ | |
| osc(notes[i], buffer, noteLength); | |
| flush_buffer(of, buffer, noteLength); | |
| }*/ | |
| int pressLength = (int)SAMPLE/2; | |
| int releaseLength = 1; | |
| int noteLength = pressLength + releaseLength; | |
| setEnvelopeSettings((int)SAMPLE/2, 1, 0., 1); | |
| //setEnvelopeSettings((int)SAMPLE/4, (int)SAMPLE/4, 0.3, 1); | |
| for(int nott = 0;nott<16;nott++){ | |
| osc(notes[nott], buffer, noteLength); | |
| int i; | |
| float env; | |
| KEY_STATE = KEY_STATE_PRESSED; | |
| for(i=0;i<pressLength;i++){ //simulating 2 seconds long key-press | |
| envelope(); | |
| buffer[i] = (unsigned char)(buffer[i] * VOLUME); | |
| } | |
| KEY_STATE = KEY_STATE_RELEASED; | |
| for(;i<noteLength;i++){ //simulating key-release | |
| envelope(); | |
| buffer[i] = (unsigned char)(buffer[i] * VOLUME); | |
| } | |
| flush_buffer(of, buffer, noteLength); | |
| } | |
| getchar(); | |
| of.close(); | |
| } | |
| void shiftEnvelopeState(){ | |
| ENVELOPE_STATE++; | |
| ENVELOPE_STATE %= 5; | |
| } | |
| void setEnvelopeState(char state){ | |
| ENVELOPE_STATE = state; | |
| } | |
| float envelope_stop(){ | |
| if(KEY_STATE == KEY_STATE_PRESSED){ | |
| shiftEnvelopeState(); | |
| envelope_attack(); | |
| } | |
| } | |
| float envelope_attack(){ | |
| if(KEY_STATE == KEY_STATE_PRESSED){ | |
| if(VOLUME == 1.){ | |
| shiftEnvelopeState(); | |
| //cout<<"shifting from attack to decay"<<endl; | |
| envelope_decay(); | |
| } | |
| else{ | |
| VOLUME = MIN(1., VOLUME + (1.0)/ENVELOPE_ATTACK); | |
| //cout<<"attack "<<VOLUME<<endl; | |
| } | |
| } | |
| else{ | |
| setEnvelopeState(ENVELOPE_STATE_RELEASE); | |
| if(VOLUME == 0.){ | |
| shiftEnvelopeState(); | |
| } | |
| else{ | |
| VOLUME = MAX(0., VOLUME - (1.0)/ENVELOPE_RELEASE); | |
| } | |
| } | |
| } | |
| float envelope_decay(){ | |
| if(KEY_STATE == KEY_STATE_PRESSED){ | |
| if(VOLUME == ENVELOPE_SUSTAIN){ | |
| shiftEnvelopeState(); | |
| //cout<<"shifting from decay to sustain"<<endl; | |
| envelope_sustain(); | |
| } | |
| else{ | |
| VOLUME = MAX(ENVELOPE_SUSTAIN, (VOLUME - (1.0)/ENVELOPE_DECAY)); | |
| //cout<<"decay "<<(VOLUME - (1.0)/ENVELOPE_DECAY)<<endl; | |
| } | |
| } | |
| else{ | |
| setEnvelopeState(ENVELOPE_STATE_RELEASE); | |
| if(VOLUME == 0.){ | |
| shiftEnvelopeState(); | |
| } | |
| else{ | |
| VOLUME = MAX(0., VOLUME - (1.0)/ENVELOPE_RELEASE); | |
| } | |
| } | |
| } | |
| float envelope_sustain(){ | |
| if(KEY_STATE == KEY_STATE_PRESSED){ | |
| VOLUME = ENVELOPE_SUSTAIN; | |
| } | |
| else{ | |
| setEnvelopeState(ENVELOPE_STATE_RELEASE); | |
| if(VOLUME == 0.){ | |
| shiftEnvelopeState(); | |
| } | |
| else{ | |
| VOLUME = MAX(0., VOLUME - (1.0)/ENVELOPE_RELEASE); | |
| } | |
| } | |
| } | |
| float envelope_release(){ | |
| if(KEY_STATE == KEY_STATE_PRESSED){ | |
| shiftEnvelopeState(); | |
| envelope_stop(); | |
| } | |
| else{ | |
| if(VOLUME == 0.){ | |
| shiftEnvelopeState(); | |
| } | |
| else{ | |
| VOLUME = MAX(0., VOLUME - (1.0)/ENVELOPE_RELEASE); | |
| } | |
| } | |
| } | |
| float envelope(){ | |
| switch(ENVELOPE_STATE){ | |
| case ENVELOPE_STATE_STOP: | |
| envelope_stop(); | |
| break; | |
| case ENVELOPE_STATE_ATTACK: | |
| envelope_attack(); | |
| break; | |
| case ENVELOPE_STATE_DECAY: | |
| envelope_decay(); | |
| break; | |
| case ENVELOPE_STATE_SUSTAIN: | |
| envelope_sustain(); | |
| break; | |
| case ENVELOPE_STATE_RELEASE: | |
| envelope_release(); | |
| break; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment