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.
This commit is contained in:
parent
e1a7320aa6
commit
642b4973ca
@ -21,12 +21,8 @@
|
||||
+ contact: j.bak@ciid.dk
|
||||
*/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <Wavetable.h>
|
||||
#include <Music.h>
|
||||
#include <hardwareSerial.h>
|
||||
#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<<SPIF))); // Maybe this can be optimised
|
||||
SPDR = dacSPI1;
|
||||
while (!(SPSR & (1<<SPIF))); // Maybe this can be optimised
|
||||
|
||||
// Frame sync high
|
||||
PORTD |= (1<<6);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -22,15 +22,29 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef Music_h // include guard
|
||||
#define Music_h
|
||||
|
||||
// current sample rate is 15625 as defined in the init() section
|
||||
#define SAMPLE_RATE 15625
|
||||
|
||||
// Number of oscillators. Set not higher than 4.
|
||||
#define NUM_OSCILLATORS 2
|
||||
#define NUM_OSCILLATORS 1
|
||||
|
||||
#ifndef NUM_OSCILLATORS
|
||||
#error NUM_OSCILLATORS should be defined in the Music.h file in the libraries folder.
|
||||
#elif (NUM_OSCILLATORS == 1)||(NUM_OSCILLATORS == 2)||(NUM_OSCILLATORS == 3)
|
||||
#else
|
||||
#error NUM_OSCILLATORS shall be 1, 2 or 3
|
||||
#endif
|
||||
|
||||
// Maximum possible value for amplification envelope
|
||||
#define MAX_ENV_GAIN 65535
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <hardwareSerial.h>
|
||||
|
||||
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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
34
software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino
Normal file
34
software/lib/MMM/examples/Music/Basic_MIDI/Basic_MIDI.ino
Normal file
@ -0,0 +1,34 @@
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
#include <Midi.h>
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
@ -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 <stdint.h>
|
||||
#include <Music.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
19
software/lib/MMM/examples/Music/Minimal/Minimal.ino
Normal file
19
software/lib/MMM/examples/Music/Minimal/Minimal.ino
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
void setup() {
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
#include <Midi.h>
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
62
software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino
Normal file
62
software/lib/MMM/examples/Music/Up_and_down/Up_and_down.ino
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// 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 <Music.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
28
software/lib/MMM/keywords.txt
Normal file
28
software/lib/MMM/keywords.txt
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user