From 642b4973ca9a9b34d7e45f91428a529cb4da23f2 Mon Sep 17 00:00:00 2001 From: Jakob Bak Date: Wed, 23 Jan 2013 19:29:10 +0100 Subject: [PATCH] Oscillator selects and examples Made it possible to select type and number of oscillators to compile (via preprocessor). Made Examples folder to library where tutorials will go in. --- software/lib/MMM/Music.cpp | 183 ++++++++++++++---- software/lib/MMM/Music.h | 23 ++- software/lib/MMM/Wavetable.h | 6 +- .../examples/Music/Basic_MIDI/Basic_MIDI.ino | 34 ++++ .../Music/Circuit_bending/Circuit_bending.ino | 44 +++++ .../MUSIC_LIBRARY_DOCUMENTATION.ino | 88 +++++++++ .../MMM/examples/Music/Minimal/Minimal.ino | 19 ++ .../Music/Minimal_test/Minimal_test.ino | 33 ++++ .../Repeating_note_with_envelope.ino | 50 +++++ .../Music/Spaghetti_tones/Spaghetti_tones.ino | 64 ++++++ .../Music/Up_and_down/Up_and_down.ino | 62 ++++++ .../sketch_jun26c/sketch_jun26c.ino | 62 ++++++ .../Up_and_down__square.ino | 68 +++++++ software/lib/MMM/keywords.txt | 28 +++ 14 files changed, 717 insertions(+), 47 deletions(-) create mode 100644 software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino create mode 100644 software/lib/MMM/examples/Music/Circuit_bending/Circuit_bending.ino create mode 100644 software/lib/MMM/examples/Music/MUSIC_LIBRARY_DOCUMENTATION/MUSIC_LIBRARY_DOCUMENTATION.ino create mode 100644 software/lib/MMM/examples/Music/Minimal/Minimal.ino create mode 100644 software/lib/MMM/examples/Music/Minimal_test/Minimal_test.ino create mode 100644 software/lib/MMM/examples/Music/Repeating_note_with_envelope/Repeating_note_with_envelope.ino create mode 100644 software/lib/MMM/examples/Music/Spaghetti_tones/Spaghetti_tones.ino create mode 100644 software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino create mode 100644 software/lib/MMM/examples/Music/Up_and_down/sketch_jun26c/sketch_jun26c.ino create mode 100644 software/lib/MMM/examples/Music/Up_and_down__square/Up_and_down__square.ino create mode 100644 software/lib/MMM/keywords.txt diff --git a/software/lib/MMM/Music.cpp b/software/lib/MMM/Music.cpp index cab244d..7539266 100644 --- a/software/lib/MMM/Music.cpp +++ b/software/lib/MMM/Music.cpp @@ -21,12 +21,8 @@ + contact: j.bak@ciid.dk */ -#include -#include - -#include -#include -#include +#include "Music.h" +#include "Wavetable.h" // Table of MIDI note values to frequency in Hertz prog_uint16_t hertsTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543}; @@ -46,7 +42,9 @@ ISR(TIMER2_COMPA_vect) { OCR2A = 127; - Music.synthInterrupt(); +// Music.synthInterrupt8bit(); + + Music.synthInterrupt12bitSine(); } @@ -378,7 +376,8 @@ uint16_t MMusic::getGain() void MMusic::noteOn(uint8_t note, uint8_t vel) { envStage = 1; - velSustain = vel; + setVelSustain(vel); + setVelPeak(vel); notePlayed = note; memcpy_P(&frequency16bit, &hertsTable[notePlayed],2); setFrequency1(frequency16bit); @@ -390,7 +389,8 @@ void MMusic::noteOn(uint8_t note, uint8_t vel) void MMusic::noteOn(uint8_t note) { envStage = 1; - velSustain = 127; + setVelSustain(127); + setVelPeak(127); notePlayed = note; memcpy_P(&frequency16bit, &hertsTable[notePlayed],2); setFrequency1(frequency16bit); @@ -507,49 +507,43 @@ void MMusic::setVelPeak(uint8_t vel) -///////////////////////////////////// +///////////////////////////////////////////////////////// // -// AUDIO INTERRUPT SERVICE ROUTINE +// 8 BIT WAVETABLE - AUDIO INTERRUPT SERVICE ROUTINE // -///////////////////////////////////// +///////////////////////////////////////////////////////// -void inline MMusic::synthInterrupt() +void inline MMusic::synthInterrupt8bit() { // Frame sync low for SPI (making it low here so that we can measure lenght of interrupt with scope) PORTD &= ~(1<<6); - - // The accumulator (16bit) keeps track of the pitch by adding the - // the amount of "index" points that the frequency has "travelled" - // since the last sample was sent to the DAC, i.e. the current phase - // of the waveform. + accumulator1 = accumulator1 + period1; - accumulator2 = accumulator2 + period2; - accumulator3 = accumulator3 + period3; - - // To use the accumulator position to find the right index in the - // waveform look-up table, we truncate it to 8bit. index1 = accumulator1 >> 8; - index2 = accumulator2 >> 8; - index3 = accumulator3 >> 8; - - oscil1 = 0; - oscil2 = 0; - oscil3 = 0; - + //oscil1 = 0; memcpy_P(&oscil1, &waveTable[index1 + waveForm1],1); + sample = (oscil1 * gain1); + +#if(NUM_OSCILLATORS==2 || NUM_OSCILLATORS==3) + + accumulator2 = accumulator2 + period2; + index2 = accumulator2 >> 8; + //oscil2 = 0; memcpy_P(&oscil2, &waveTable[index2 + waveForm2],1); + sample += (oscil2 * gain2); + +#endif +#if NUM_OSCILLATORS==3 + + accumulator3 = accumulator3 + period3; + index3 = accumulator3 >> 8; + //oscil3 = 0; memcpy_P(&oscil3, &waveTable[index3 + waveForm3],1); - - - - // The DAC formatting routine below assumes the sample to be transmitted - // is in the higher 12 bits of the 2 byte variable, so we shift the - // sample up 6 bits each which adds up to 4 bits. - // The individual gains for each oscillator is added. - sample = (oscil1 * gain1); - sample += (oscil2 * gain2); sample += (oscil3 * gain3); + +#endif + sample >>= 10; @@ -621,3 +615,114 @@ void inline MMusic::synthInterrupt() PORTD |= (1<<6); } + + + + +///////////////////////////////////////////////////////// +// +// 12 BIT SINEWAVE - AUDIO INTERRUPT SERVICE ROUTINE +// +///////////////////////////////////////////////////////// + + +void MMusic::synthInterrupt12bitSine() +{ + // Frame sync low for SPI (making it low here so that we can measure lenght of interrupt with scope) + PORTD &= ~(1<<6); + + accumulator1 = accumulator1 + period1; + index1 = accumulator1 >> 4; + memcpy_P(&oscil1, &sineTable[index1],2); + sample = (oscil1 * gain1) << 2; + +#if(NUM_OSCILLATORS==2 || NUM_OSCILLATORS==3) + + accumulator2 = accumulator2 + period2; + index2 = accumulator2 >> 4; + memcpy_P(&oscil2, &sineTable[index2],2); + sample += (oscil2 * gain2) << 2; + +#endif +#if NUM_OSCILLATORS==3 + + accumulator3 = accumulator3 + period3; + index3 = accumulator3 >> 4; + memcpy_P(&oscil3, &sineTable[index3],2); + sample += (oscil3 * gain3) << 2; + +#endif + + sample >>= 16; + + + // AMPLIFICATION ENVELOPE + // Amplification envelope is calculated here + if(envelopeOn) { + + // Attack + if(envStage == 1) { + env += attack; + if(velPeak < env) { + env = velPeak; + envStage = 2; + } + } + // Decay + else if(envStage == 2) { + env -= decay; + if(env < velSustain || MAX_ENV_GAIN < env) { + env = velSustain; + envStage = 3; + } + } + // Sustain + else if (envStage == 3) { + env = velSustain; + } + + // Release + else if (envStage == 4) { + env -= release; + if(MAX_ENV_GAIN < env) { + env = 0; + envStage = 0; + } + } + /* + // No gain + else if (envStage == 0) { + env = 0; + //accumulator1 = 0; + //accumulator2 = 0; + //accumulator3 = 0; + } + */ + } else { + env = 65535; + } + + // Adding the amplification envelope (16bit) we bring it back to the 16bit frame again afterwards. + sample = (env * sample) >> 16; + + // Formatting the samples to be transfered to the MCP4921 DAC + dacSPI0 = sample >> 8; + dacSPI0 >>= 4; + dacSPI0 |= 0x30; + dacSPI1 = sample >> 4; + + SPCR |= (1 << MSTR); + + // transmit value out the SPI port + SPDR = dacSPI0; + while (!(SPSR & (1< +#include +#include + class MMusic { public: @@ -38,7 +52,8 @@ public: void init(); // AUDIO INTERRUPT SERVICE ROUTINE - void synthInterrupt(); + void synthInterrupt8bit(); + void synthInterrupt12bitSine(); // FREQUENCY AND DETUNE FUNCTIONS void setFrequency(float frequency); @@ -169,3 +184,5 @@ private: }; extern MMusic Music; + +#endif // close guard diff --git a/software/lib/MMM/Wavetable.h b/software/lib/MMM/Wavetable.h index 6094117..0e6a7d4 100644 --- a/software/lib/MMM/Wavetable.h +++ b/software/lib/MMM/Wavetable.h @@ -1,5 +1,5 @@ /* - Music.h - Music library + Wavetable.h - Music library Copyright (c) 2012 Copenhagen Institute of Interaction Design. All right reserved. @@ -21,10 +21,6 @@ + contact: j.bak@ciid.dk */ -//uint32_t envTimeTable[] = {1,2,5,8,11,14,18,22,27,31,36,41,46,52,58,64,70,76,82,89,96,103,110,117,125,132,140,148,156,164,172,181,189,198,207,216,225,234,243,252,262,272,281,291,301,311,322,332,343,353,364,374,385,396,407,419,430,441,453,464,476,488,500,512,524,536,548,560,573,585,598,610,623,636,649,662,675,688,702,715,729,742,756,769,783,797,811,825,839,853,868,882,896,911,925,940,955,970,985,1000,1015,1030,1045,1060,1075,1091,1106,1122,1137,1153,1169,1185,1201,1217,1233,1249,1265,1281,1298,1314,1331,1347,1364,1380,1397,1414,1431,1448,1465,1482,1499,1516,1533,1551,1568,1586,1603,1621,1638,1656,1674,1692,1710,1728,1746,1764,1782,1800,1818,1837,1855,1873,1892,1911,1929,1948,1967,1986,2004,2023,2042,2061,2081,2100,2119,2138,2158,2177,2197,2216,2236,2255,2275,2295,2315,2334,2354,2374,2394,2414,2435,2455,2475,2495,2516,2536,2557,2577,2598,2618,2639,2660,2681,2702,2723,2744,2765,2786,2807,2828,2849,2870,2892,2913,2935,2956,2978,2999,3021,3043,3064,3086,3108,3130,3152,3174,3196,3218,3240,3263,3285,3307,3330,3352,3375,3397,3420,3442,3465,3488,3510,3533,3556,3579,3602,3625,3648,3671,3694,3718,3741,3764,3787,3811,3834,3858,3881,3905,3929,3952,3976,4000,4024,4048,4072,4095}; - -//prog_uint16_t hertzTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543}; - // Look-up table for sine waveform in 12 bit resolution in // both amplitude and time. diff --git a/software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino b/software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino new file mode 100644 index 0000000..8594fa3 --- /dev/null +++ b/software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino @@ -0,0 +1,34 @@ +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. + +#include +#include + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // We initialize the MIDI engine by calling Midi.init() + Midi.init(); + + // Choosing the sine wave oscillator. + Music.setWaveform(3); + + // Enabling envelope, otherwise the synth would just play constant tones. + //Music.enableEnvelope(); + +} + +void loop() { + + // The MIDI must be used with the external + // "IAC2CFO.pde" Processing sketch. + Midi.checkMidi(); + +} + diff --git a/software/lib/MMM/examples/Music/Circuit_bending/Circuit_bending.ino b/software/lib/MMM/examples/Music/Circuit_bending/Circuit_bending.ino new file mode 100644 index 0000000..87c3054 --- /dev/null +++ b/software/lib/MMM/examples/Music/Circuit_bending/Circuit_bending.ino @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////// +// CIRCUIT BENDING +// This came about by accident. +// Upload the code to your board, plug into loud speakers +// and touch the bare pins to make some awesome noise :D +////////////////////////////////////////////////////////// + +#include +#include + + +float s; +float frequency = 220.0; +float detune = 0.01; +float bend = 0.0; + +void setup(){ + + Serial.begin(9600); + + Music.init(); + + Music.setSaw(); + Music.setDetune(detune); + Music.setFrequency(220); + +} + +void loop() { + + s = analogRead(0); + bend = mapFloat(s, 0.0, 1023.0, -2.0, 2.0); + Music.pitchBend(bend); + frequency = Music.getNoteFrequency(48); + //Serial.println(frequency); + //delay(100); + +} + +float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + diff --git a/software/lib/MMM/examples/Music/MUSIC_LIBRARY_DOCUMENTATION/MUSIC_LIBRARY_DOCUMENTATION.ino b/software/lib/MMM/examples/Music/MUSIC_LIBRARY_DOCUMENTATION/MUSIC_LIBRARY_DOCUMENTATION.ino new file mode 100644 index 0000000..3f46436 --- /dev/null +++ b/software/lib/MMM/examples/Music/MUSIC_LIBRARY_DOCUMENTATION/MUSIC_LIBRARY_DOCUMENTATION.ino @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////// +// DON'T TRY TO RUN THIS SKETCH, IT IS FOR DOCUMENTATION PURPOSES ONLY // +///////////////////////////////////////////////////////////////////////// + +// These are the music functions that are available for you to use in you sketches. +// You can see examples of how some of them are used (the most basic ones) in the +// Apps folder that downloaded with the MM library. + +// In the following you can see the variable type that the function takes as an argument (float, uint8_t or uint16_t) +// The weirdly looking "uint16_t" and "uint8_t" is just unsigned 16 and 8 bit integers. So instead of having +// both negative and positive values, they only have positive values from 0 - 255 (8bit) and 0 - 65535 (16bit). +// If you copy a function from here to your arduino sketch, just change the word "float", "uint8_t", etc into the +// variable name that you uses in your sketch. + + +// INITIALIZER +// Use this to start the synth engine. It defaults to a sine tone at 110Hz, no envelope and no detune. +Music.init(); + + +// FREQUENCY AND DETUNE FUNCTIONS +// Use these functions to set the frequency and detune parameters of the synth. +Music.setFrequency(float); // Set frequencies of all oscillators at once. Does _not_ affect detune. +Music.setFrequency1(float); // Set frequency of individual oscillators. +Music.setFrequency2(float); // +Music.setFrequency3(float); // +Music.setDetune(float); // Set the detune of all oscillators at once. Does _not_ affect the base frequencies. +Music.setDetune2(float); // Set the detune of oscillator 2 and 3 individually (oscillator 1 stays fixed) +Music.setDetune3(float); +Music.pitchBend(float); // This function detunes the pitch without affecting the detune parameters' individual + // 'spread'. Takes a float. + + +// WAVEFORM FUNCTIONS +// Switch between the different waveforms for the oscillators. It sets all of them at once. +Music.setSine(); +Music.setSaw(); +Music.setSquare(); + + +// GAIN FUNCTIONS +// Set the gain of the oscillators all at once or individually. You can send either floats or uint16_t to the +// function and it figures out to use the correct function automagically :) +Music.setGain(float); // 0.0 - 1.0 +Music.setGain1(float); // 0.0 - 1.0 +Music.setGain2(float); // 0.0 - 1.0 +Music.setGain3(float); // 0.0 - 1.0 +// using floats in your own calculations can be heavy on the processor, so there is the option of passing 16bit integers +// instead, since this is what it gets converted to anyway internally in the sound engine. +Music.setGain(uint16_t value); // 0 - 65535 +Music.setGain1(uint16_t value); // 0 - 65535 +Music.setGain2(uint16_t value); // 0 - 65535 +Music.setGain3(uint16_t value); // 0 - 65535 + + +// NOTE FUNCTIONS +// These functions triggers a note to be played. The noteOff() functions turns the note off again. +// They come both with note and velocity information (for noteOn). If you don't know what that is, +// just use the ones with the least arguments. +// To get a proper note sound call Music.enableEnvelopes() [see below] before calling the noteOn function. +// You just have to do that once in the setup for example. +Music.noteOn(uint8_t note, uint8_t vel); // 0 - 127 +Music.noteOn(uint8_t note); // 0 - 127 +Music.noteOff(uint8_t note); // 0 - 127 +Music.noteOff(); +// This function returns the frequency of a MIDI note number sent to it. +Music.getNoteFrequency(uint8_t); // 0 - 127 + + +// ENVELOPE FUNCTIONS +// These functions enables and sets the parameters of the internal envelope which creates dynamics for the notes +// being played. You can read about ADSR envelopes here: http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope +// When using the envelope you can only hear sound when you are triggering the notes with the note functions. In order +// to get dynamics without triggering the note object you must have the envelope turned off, for example using +// the Music.disableEnvelope() function [already set by default in the init() function]. You can then control the +// dynamics of the sound with the overall or individual setGain() functions. +Music.enableEnvelope(); +Music.disableEnvelope(); +// Setting the parameters for the envelope you send an 8bit number between 0 and 127 to the functions below. 0 is a very fast +// rise or decay in sound, whereas 127 is very long. Sustain is the sound level where 0 is silent and 127 is full gain. +// You must experiment with what suits your musical taste :) +// These parameters can of course be adjusted during the physics code for interesting results, but be aware that when +// using the sine wave oscillator (which is more processor intensive) the sound can hang or have glitches if you alter +// these parameters too quickly or set them at extremes. Try it out. +Music.setAttack(uint8_t att); // 0 - 127 +Music.setDecay(uint8_t dec); // 0 - 127 +Music.setSustain(uint8_t sus); // 0 - 127 +Music.setRelease(uint8_t rel); // 0 - 127 diff --git a/software/lib/MMM/examples/Music/Minimal/Minimal.ino b/software/lib/MMM/examples/Music/Minimal/Minimal.ino new file mode 100644 index 0000000..9eae6a3 --- /dev/null +++ b/software/lib/MMM/examples/Music/Minimal/Minimal.ino @@ -0,0 +1,19 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +void setup() { + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + +} + +void loop() { + +} + diff --git a/software/lib/MMM/examples/Music/Minimal_test/Minimal_test.ino b/software/lib/MMM/examples/Music/Minimal_test/Minimal_test.ino new file mode 100644 index 0000000..52ceecf --- /dev/null +++ b/software/lib/MMM/examples/Music/Minimal_test/Minimal_test.ino @@ -0,0 +1,33 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include +#include + +uint8_t i = 0; + +void setup() { + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + Music.setFrequency(110); + Music.setGain1(1.0f); + Music.setGain2(1.0f); + Music.setGain3(1.0f); + Music.setWaveform1(0); + Music.setWaveform2(0); + Music.setWaveform3(0); + //Music.setDetune2(0.0015478); + //Music.setDetune3(-0.0012894); + +} + +void loop() { + + Midi.checkMidi(); + +} + diff --git a/software/lib/MMM/examples/Music/Repeating_note_with_envelope/Repeating_note_with_envelope.ino b/software/lib/MMM/examples/Music/Repeating_note_with_envelope/Repeating_note_with_envelope.ino new file mode 100644 index 0000000..6d49757 --- /dev/null +++ b/software/lib/MMM/examples/Music/Repeating_note_with_envelope/Repeating_note_with_envelope.ino @@ -0,0 +1,50 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +// variables for this sketch +boolean noteIsOn = false; +int note = 48; + +long time = 0; +long lastTime = 0; +long beatTime = 1000; + + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // enabling the envelope lets us define an gain envelope for the synth + // without having to specify it in our loop() or physics code. + Music.enableEnvelope(); + Music.setAttack(4); + Music.setDecay(64); + Music.setSustain(64); + Music.setRelease(64); + +} + +void loop() { + + // This short routine loops note over and over again + time = millis(); + if(time - lastTime > beatTime) { + if(!noteIsOn) { + Music.noteOn(note); + noteIsOn = true; + } else { + Music.noteOff(); + noteIsOn = false; + } + lastTime = time; + } + +} + diff --git a/software/lib/MMM/examples/Music/Spaghetti_tones/Spaghetti_tones.ino b/software/lib/MMM/examples/Music/Spaghetti_tones/Spaghetti_tones.ino new file mode 100644 index 0000000..9f3be8c --- /dev/null +++ b/software/lib/MMM/examples/Music/Spaghetti_tones/Spaghetti_tones.ino @@ -0,0 +1,64 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +// variables for this sketch +float gain = 1.0; +float c = 220; // center frequency +float f1 = 1; +float f2 = 1; +float f3 = 1; +float m1 = 1.0011; +float m2 = 1.0012; +float m3 = 1.0013; + + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // Choosing the sine wave oscillator (optional since this is already the default). + Music.setWaveform(0); + + // Setting the initial frequency for all three oscillators. + Music.setFrequency(c); + + // Detuning the three oscillators slightly to create movement in the sound. + Music.setDetune(0.002); + +} + +void loop() { + + // This short routine creates a + + Music.setFrequency1(c*f1); + Music.setFrequency2(c*f2); + Music.setFrequency3(c*f3); + + f1 *= m1; + f2 *= m2; + f3 *= m3; + + if(f1 > 4.0) m1 = 0.9745; + if(f2 > 4.0) m2 = 0.9852; + if(f3 > 4.0) m3 = 0.9975; + + if(f1 < 0.25) m1 = 1.0754; + if(f2 < 0.25) m2 = 1.0573; + if(f3 < 0.25) m3 = 1.0386; + + if(millis() > 10000) { + Music.setGain(gain); + gain *= 0.999; + } + + +} + diff --git a/software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino b/software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino new file mode 100644 index 0000000..5bf6647 --- /dev/null +++ b/software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino @@ -0,0 +1,62 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +// variables for this sketch +boolean noteIsOn = false; +int n = 0; +int dir = 1; +int rootNote = 48; +int note[] = {0,2,3,5,7,9,10,12,14}; + +long time = 0; +long lastTime = 0; +long beatTime = 100; + + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // enabling the envelope lets us define an gain envelope for the synth + // without having to specify it in our loop() or physics code. + Music.enableEnvelope(); + Music.setAttack(4); + Music.setDecay(90); + Music.setSustain(64); + Music.setRelease(64); + +} + +void loop() { + + // This short routine loops note over and over again + time = millis(); + if(time - lastTime > beatTime) { + if(!noteIsOn) { + Music.noteOn(rootNote+note[n]); + noteIsOn = true; + n = n + dir; + if(n > 7) + { + dir = -1; + } + else if(n < 1) + { + dir = 1; + } + } else { + Music.noteOff(); + noteIsOn = false; + } + lastTime = time; + } + +} + diff --git a/software/lib/MMM/examples/Music/Up_and_down/sketch_jun26c/sketch_jun26c.ino b/software/lib/MMM/examples/Music/Up_and_down/sketch_jun26c/sketch_jun26c.ino new file mode 100644 index 0000000..12ba038 --- /dev/null +++ b/software/lib/MMM/examples/Music/Up_and_down/sketch_jun26c/sketch_jun26c.ino @@ -0,0 +1,62 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +// variables for this sketch +boolean noteIsOn = false; +int n = 0; +int dir = 1; +int rootNote = 48; +int note[] = {0,2,3,5,7,9,10,12,14}; + +long time = 0; +long lastTime = 0; +long beatTime = 100; + + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // enabling the envelope lets us define an gain envelope for the synth + // without having to specify it in our loop() or physics code. + Music.enableEnvelope(); + Music.setAttack(8); + Music.setDecay(70); + Music.setSustain(24); + Music.setRelease(90); + +} + +void loop() { + + // This short routine loops note over and over again + time = millis(); + if(time - lastTime > beatTime) { + if(!noteIsOn) { + Music.noteOn(rootNote+note[n]); + noteIsOn = true; + n = n + dir; + if(n > 7) + { + dir = -1; + } + else if(n < 1) + { + dir = 1; + } + } else { + Music.noteOff(); + noteIsOn = false; + } + lastTime = time; + } + +} + diff --git a/software/lib/MMM/examples/Music/Up_and_down__square/Up_and_down__square.ino b/software/lib/MMM/examples/Music/Up_and_down__square/Up_and_down__square.ino new file mode 100644 index 0000000..b7c5a19 --- /dev/null +++ b/software/lib/MMM/examples/Music/Up_and_down__square/Up_and_down__square.ino @@ -0,0 +1,68 @@ + +// This needs to be in all sketches at the moment +#include + +// The Music and Midi objects are automatically instantiated when the header file is included. +// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)" +// You still need to call Music.init() and Midi.init() in the setup() function below. +#include + +// variables for this sketch +boolean noteIsOn = false; +int n = 0; +int dir = 1; +int rootNote = 26; +int note[] = {0,2,3,5,7,9,10,12,14}; + +long time = 0; +long lastTime = 0; +long beatTime = 80; + + +void setup() { + + // We initialise the sound engine by calling Music.init() which outputs a tone + Music.init(); + + // Choosing the square wave oscillator. + Music.setWaveform(1); + + // Detuning the three oscillators slightly to create movement in the sound. + Music.setDetune(0.008); + + // enabling the envelope lets us define an gain envelope for the synth + // without having to specify it in our loop() or physics code. + Music.enableEnvelope(); + Music.setAttack(8); + Music.setDecay(90); + Music.setSustain(48); + Music.setRelease(64); + +} + +void loop() { + + // This short routine loops note over and over again + time = millis(); + if(time - lastTime > beatTime) { + if(!noteIsOn) { + Music.noteOn(rootNote+note[n]); + noteIsOn = true; + n = n + dir; + if(n > 7) + { + dir = -1; + } + else if(n < 1) + { + dir = 1; + } + } else { + Music.noteOff(); + noteIsOn = false; + } + lastTime = time; + } + +} + diff --git a/software/lib/MMM/keywords.txt b/software/lib/MMM/keywords.txt new file mode 100644 index 0000000..996c5f8 --- /dev/null +++ b/software/lib/MMM/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring Map For MMM Library +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Music KEYWORD1 +Midi KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +init KEYWORD2 +checkMidi KEYWORD2 +enableEnvelope KEYWORD2 +diableEnvelope KEYWORD2 +setDetune KEYWORD2 + + + +####################################### +# Constants (LITERAL1) +####################################### + +NUM_OSCILLATORS LITERAL1 \ No newline at end of file