#define BUFFER_SIZE 16 #define SAMPLE_RATE 1600 //const unsigned long period = 1000000 / SAMPLE_RATE; #define PHOTO_INPUT 3 #define AUDIO_OUTPUT 9 void audio_init() { // Make sure the PWM is at its maximum frequency. TCCR1A = 1; TCCR1B = 9; } // Conversion formulaes from base -1, +1 <-> base 0, 255: // Base [-1,+1] -> base [0,255]: c(x) = 2x / 255 - 1 // Base [0,255] -> base [-1,+1]: c^-1(x) = 255 (x+1) / 2 ~= 127 * (x+1) // Basic class /////////////////////////////////////////// class AudioNode { public: byte output[BUFFER_SIZE]; AudioNode() { } void getOutput(byte* value) { memcpy(value, this->output, BUFFER_SIZE); } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { memset(this->output, 0, BUFFER_SIZE); return this->output; } }; // Generators /////////////////////////////////////////// class AudioSquare : public AudioNode { public: float frequency; int amplitude; float _phase; AudioSquare(float frequency, int amplitude) { this->frequency = frequency; this->amplitude = amplitude; this->_phase = 0; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; float num = (float)this->frequency / (float)SAMPLE_RATE; byte* out = this->output; for (i=0; i_phase < 0.5 ? 127 - this->amplitude : 127 + this->amplitude); this->_phase += num; if (this->_phase > 1) this->_phase = 0; } return this->output; } }; //class AudioTriangle : public AudioNode { //public: // int frequency; // int amplitude; // float width; // float _phase; // // AudioTriangle(int frequency, int amplitude, float width = 0.5) { // this->frequency = frequency; // this->amplitude = amplitude; // this->width = width; // this->_phase = 0; // } // if( phase < d->width ) *out = (SAMPLE) (d->width == 0.0) ? 1.0 : -1.0 + 2.0 * phase / d->width; // else *out = (SAMPLE) (d->width == 1.0) ? 0 : 1.0 - 2.0 * (phase - d->width) / (1.0 - d->width); // // byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { // int i; // float num = (float)this->frequency / (float)SAMPLE_RATE; // byte* out = this->output; // for (i=0; i_phase <= this->width) { // *out++ = (byte) this->amplitude // *out++ = (byte) (this->width == 0.0 ? 255 : -127 + 2 * this->amplitude * this->_phase / this->width); // } else { // *out++ = (byte) (127 - this->amplitude * (this->_phase - this->width) / (1.0 - this->width)); // } // this->_phase += num; // if (this->_phase > 1) this->_phase = 0; // } // return this->output; // } // //}; class AudioSine : public AudioNode { public: float frequency; int amplitude; float _phase; AudioSine(float frequency, int amplitude) { this->frequency = frequency; this->amplitude = amplitude; this->_phase = 0; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; float num = (float)this->frequency / (float)SAMPLE_RATE; byte* out = this->output; for (i=0; i_phase ) * this->amplitude))) + 127); this->_phase += num; if (this->_phase > 1) this->_phase = 0; } return this->output; } }; class AudioConstant : public AudioNode { public: int value; AudioConstant(int value) { this->value = value; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { memset(this->output, this->value, BUFFER_SIZE); return this->output; } }; class AudioAnalogRead : public AudioNode { public: int pin; AudioAnalogRead(int pin) { this->pin = pin; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { memset(this->output, (byte)map(analogRead(this->pin), 0, 1023, 0, 255), BUFFER_SIZE); return this->output; } }; class AudioOutput : public AudioNode { public: int pin; AudioOutput(int pin) { this->pin = pin; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; unsigned long period = 1000000 / SAMPLE_RATE - 7; // subtract 7 us to make up for analogWrite overhead - determined empirically for (i=0; ipin, (int)*input1++); delayMicroseconds(period); } return NULL; } }; class AudioNoise : public AudioNode { int amplitude; public: AudioNoise(int amplitude = 255) { this->amplitude = amplitude; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; byte* out = this->output; for (i=0; iamplitude); } return this->output; } }; class AudioAdd : public AudioNode { public: AudioAdd() {} byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; byte* out = this->output; for (i=0; ioutput; } }; class AudioProduct : public AudioNode { public: AudioProduct() {} byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; byte* out = this->output; for (i=0; ioutput; } }; class AudioBlend : public AudioNode { public: byte blend; AudioBlend(byte blend) { this->blend = blend; } byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { int i; byte oneMinusBlend = 255 - blend; byte* out = this->output; for (i=0; ioutput; } }; class AudioVoice : public AudioNode { public: AudioNoise noise; AudioSquare voice; AudioSine lfo; AudioProduct prod; AudioAdd add; AudioVoice() : noise(100), voice(440, 100), lfo(1, 100) {} byte* fire(const byte* input1 = NULL, const byte* input2 = NULL) { byte* out = this->add.fire( this->lfo.fire(), this->voice.fire() ); memcpy(this->output, out, BUFFER_SIZE); return this->output; } }; void setup() { audio_init(); Serial.begin(19200); } #define AUDIO_PLAY(time, startTime, action) \ (startTime) = millis(); \ while (millis() - (startTime) < (time)) { \ (action); \ } \ //void audio_play(unsigned long time, AudioNode *node) { // unsigned long startTime = millis(); // while (millis() - startTime < time) { // // } // //} AudioNoise noiseWav; AudioSquare lfo(1, 100); AudioProduct prod; AudioSine sine(220, 127); AudioOutput output(AUDIO_OUTPUT); AudioSquare squareWav(440, 120); AudioAdd add; AudioVoice voice; AudioAnalogRead photoIn(PHOTO_INPUT); int minVal = 10000; int maxVal = -10000; void updateStatistics(int x) { if (x < minVal) minVal = x; if (x > maxVal) maxVal = x; } int normalize(int x, int low, int high) { return ((float)(x - minVal)) / (maxVal - minVal) * (high - low) + low; } void loop() { int amp = 100; int val; unsigned long startTime; int frequency = 200; for (;;) { // val = analogRead(PHOTO_INPUT); // updateStatistics(val); // // // squareWav.frequency = normalize(val, 200, 1000); output.fire ( prod.fire (squareWav.fire(), photoIn.fire() ) ); // output.fire ( prod.fire (voice.fire(), photoIn.fire() ) ); /* AUDIO_PLAY(5000, startTime, output.fire (sine.fire() )); delay(1000); AUDIO_PLAY(100, startTime, output.fire( voice.fire() )); delay(50); voice.voice.frequency = random(355, 430); AUDIO_PLAY(100, startTime, output.fire( voice.fire() )); delay(random(30, 90)); voice.voice.frequency = random(500, 800); voice.lfo.frequency = random(30, 60); AUDIO_PLAY(400, startTime, output.fire( add.fire( voice.fire(), noiseWav.fire() ) ) ); voice.voice.frequency = random(500, 800); voice.lfo.frequency = random(30, 60); AUDIO_PLAY(10000, startTime, output.fire( prod.fire( voice.fire(), lfo.fire() ) )); */ // startTime = millis(); // while (millis() - startTime < 100) { // output.fire( voice.fire() ); // } // delay(50); // startTime = millis(); // while (millis() - startTime < 100) { // output.fire( voice.fire() ); // } // delay(300); // startTime = millis(); // while (millis() - startTime < 500) { // output.fire( squareWav.fire() ); // } // delay(2000); // output.fire( squareWav.fire() ); // output.fire( prod.fire( squareWav.fire(), lfo.fire() ) ); } // output.fire( blender.fire( prod.fire( squareWav.fire(), lfo.fire() ), noiseWav.fire() ) ); }