forked from darwingrosse/ArdCore-Code
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
very usable delay program...somehow had not gotten uploaded
- Loading branch information
1 parent
41fed72
commit c23f652
Showing
39 changed files
with
2,739 additions
and
5 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,288 @@ | ||
// ============================================================ | ||
// | ||
// Program: ArdCore Drum Sample Player | ||
// | ||
// Description: | ||
// | ||
// This is a very lo-fi drum sample player for 8 sounds. | ||
// | ||
// I/O Usage: | ||
// Knob A0: Sound selector (summed with input A2) | ||
// Knob A1: Pitch (summed with input A3). Center value is normal pitch. | ||
// Analog In A2: Sound selection (summed with value of knob A0) | ||
// Analog In A3: VC Pitch (summed with value of knob A1) | ||
// Digital Out D0: Not used | ||
// Digital Out D1: Not used | ||
// Clock In: Trigger sound | ||
// Analog Out: Audio out | ||
// | ||
// This sketch was generated by the drum sketch | ||
// generator, programmed by Alfonso Alba (fac) | ||
// E-mail: [email protected] | ||
// | ||
// ============================================================ | ||
// | ||
// License: | ||
// | ||
// This software is licensed under the Creative Commons | ||
// Attribution-NonCommercial license. This license allows you | ||
// to tweak and build upon the code for non-commercial purposes, | ||
// without the requirement to license derivative works on the | ||
// same terms. If you wish to use this (or derived) work for | ||
// commercial work, please contact 20 Objects LLC at our website | ||
// (www.20objects.com). | ||
// | ||
// For more information on the Creative Commons CC BY-NC license, | ||
// visit http://creativecommons.org/licenses/ | ||
// | ||
// ================= start of global section ================== | ||
|
||
|
||
// Here we include the sample data files, which were automatically | ||
// generated by a custom C program. In the future, I may release | ||
// an executable version of this program so you can make your | ||
// own sample banks | ||
|
||
#include <avr/pgmspace.h> | ||
|
||
#include "pitch_table.h" | ||
#include "sample0.h" | ||
#include "sample1.h" | ||
#include "sample2.h" | ||
#include "sample3.h" | ||
#include "sample4.h" | ||
#include "sample5.h" | ||
#include "sample6.h" | ||
#include "sample7.h" | ||
|
||
// constants related to the Arduino Nano pin use | ||
#define clkIn 2 // the digital (clock) input | ||
#define digPin0 3 // the digital output pin D0 | ||
#define digPin1 4 // the digital output pin D1 | ||
#define pinOffset 5 // the first DAC pin (from 5-12) | ||
|
||
// constants related to the sample player | ||
#define NUM_SAMPLES 8 // number of samples stored in flash RAM | ||
#define MAX_SAMPLE_SIZE 1632 // maximum length of each sound | ||
|
||
// This array stores pointers to sample data in flash RAM | ||
prog_uchar *sample_data[NUM_SAMPLES] = { | ||
sample0_data, sample1_data, sample2_data, sample3_data, | ||
sample4_data, sample5_data, sample6_data, sample7_data | ||
}; | ||
|
||
// This one stores the size of each sample | ||
short sample_size[NUM_SAMPLES] = { | ||
sample0_size, sample1_size, sample2_size, sample3_size, | ||
sample4_size, sample5_size, sample6_size, sample7_size | ||
}; | ||
|
||
// This one stores the samplerate of each sound in samples per microsecond | ||
float sample_fs_micro[NUM_SAMPLES] = { | ||
sample0_fs_micro, sample1_fs_micro, sample2_fs_micro, sample3_fs_micro, | ||
sample4_fs_micro, sample5_fs_micro, sample6_fs_micro, sample7_fs_micro | ||
}; | ||
|
||
|
||
// This is the SRAM buffer where the sound being played is stored | ||
unsigned char sample[MAX_SAMPLE_SIZE]; | ||
|
||
// Some global variables | ||
char curSample = -1; // current sample number (0 to NUM_SAMPLES-1) | ||
short curSize = 0; // size in samples of current sound | ||
long curFSmicro = 0; // sample rate of current sound | ||
float envStart = 0; // offset where decay starts (in samples) | ||
|
||
short curVal0 = 0; // stores the value of analog input 0 | ||
short curVal1 = 0; // stores the value of analog input 1 | ||
short curVal2 = 0; // stores the value of analog input 2 | ||
short curVal3 = 0; // stores the value of analog input 3 | ||
unsigned long curTime = 0; // current time in microseconds | ||
unsigned long trigTime = 0; // time at which the sound was triggered | ||
char trigState = 0; // indicates if a sound is being played | ||
|
||
// variables for interrupt handling of the clock input | ||
volatile char clkState = LOW; | ||
|
||
|
||
// This function updates the sample buffer when a new sound is selected | ||
// and also computes the playback samplerate according to the pitch | ||
// Inputs: n = new sample number, pitch = pitch factor | ||
void UpdateSample(int n, long pitch) { | ||
// limit n according to the maximum number of stored sounds | ||
if (n >= NUM_SAMPLES) n = NUM_SAMPLES - 1; | ||
|
||
// check if we really need to load a new waveform | ||
if (n != curSample) { | ||
// samples stored in flash RAM may be larger than the available buffer | ||
// so we must crop the sample when needed | ||
curSize = (sample_size[n] < MAX_SAMPLE_SIZE) ? sample_size[n] : MAX_SAMPLE_SIZE; | ||
|
||
// copy the sample in flash RAM to the buffer in SRAM | ||
memcpy_P(sample, sample_data[n], curSize); | ||
|
||
// update current sample number | ||
curSample = n; | ||
} | ||
|
||
// compute the playback samplerate taking the pitch factor into account; | ||
// this is specified in samples per microsecond | ||
curFSmicro = (long)(sample_fs_micro[curSample] * pitch); | ||
} | ||
|
||
|
||
// ==================== start of setup() ====================== | ||
|
||
// This setup routine should be used in any ArdCore sketch that | ||
// you choose to write; it sets up the pin usage, and sets up | ||
// initial state. Failure to properly set up the pin usage may | ||
// lead to damaging the Arduino hardware, or at the very least | ||
// cause your program to be unstable. | ||
|
||
void setup() | ||
{ | ||
// set up the digital (clock) input | ||
pinMode(clkIn, INPUT); | ||
|
||
// set up the digital outputs | ||
pinMode(digPin0, OUTPUT); | ||
digitalWrite(digPin0, LOW); | ||
pinMode(digPin1, OUTPUT); | ||
digitalWrite(digPin1, LOW); | ||
|
||
// set up the 8-bit DAC output pins | ||
for (int i=0; i<8; i++) { | ||
pinMode(pinOffset+i, OUTPUT); | ||
digitalWrite(pinOffset+i, LOW); | ||
} | ||
|
||
// Make sure some sample is loaded | ||
UpdateSample(0, 1); | ||
dacOutputFast(128); | ||
|
||
// set up an interrupt handler for the clock in. If you | ||
// aren't going to use clock input, you should probably | ||
// comment out this call. | ||
// Note: Interrupt 0 is for pin 2 (clkIn) | ||
attachInterrupt(0, isr, RISING); | ||
} | ||
|
||
|
||
// This is the main loop | ||
|
||
void loop() | ||
{ | ||
unsigned long deltaT = 0;; | ||
long p, s, n, out = 128; | ||
|
||
// check to see if the clock as been set | ||
if (clkState == HIGH) { | ||
clkState = LOW; // clock pulse acknowledged | ||
trigState = 1; // a sound has been triggered | ||
trigTime = micros(); // remember starting time | ||
|
||
// Poll the analog inputs and update their values | ||
// This is only done at sample-start to save resources | ||
curVal0 = deJitter(analogRead(0), curVal0); | ||
curVal1 = deJitter(analogRead(1), curVal1); | ||
curVal2 = deJitter(analogRead(2), curVal2); | ||
curVal3 = deJitter(analogRead(3), curVal3); | ||
|
||
// Read pitch factor from lookup table | ||
p = pgm_read_dword_near(pitch_table + (curVal1 + curVal3)); | ||
|
||
// Load new sample if necessary and update playback samplerate | ||
UpdateSample((curVal0 + curVal2) >> 7, p); | ||
} | ||
|
||
// Check if a sound is being played | ||
if (trigState) { | ||
// Obtain current time | ||
curTime = micros(); | ||
|
||
// Obtain time since the sound was triggered; | ||
// a correction is made in the unlikely case the clock overflows | ||
deltaT = (curTime >= trigTime) ? (curTime - trigTime) : ((0xFFFFFFFF - trigTime + curTime) + 1); | ||
|
||
// Convert time to samples and separate integer from fractional part | ||
s = deltaT * curFSmicro; | ||
n = s >> 16; | ||
p = s & 0xFFFF; | ||
|
||
// Check if the sound hasn't reached its end | ||
if (n < curSize - 1) { | ||
// Compute output by linear interpolation and apply envelope | ||
out = ((65536 - p) * sample[n] + p * sample[n+1]) >> 16; | ||
} else { | ||
out = 128; | ||
trigState = 0; // sample has ended | ||
} | ||
|
||
dacOutputFast(out); | ||
} | ||
} | ||
|
||
|
||
// =================== convenience routines =================== | ||
|
||
// These routines are some things you will need to use for | ||
// various functions of the hardware. Explanations are provided | ||
// to help you know when to use them. | ||
|
||
// isr() - quickly handle interrupts from the clock input | ||
// ------------------------------------------------------ | ||
void isr() | ||
{ | ||
// Note: you don't want to spend a lot of time here, because | ||
// it interrupts the activity of the rest of your program. | ||
// In most cases, you just want to set a variable and get | ||
// out. | ||
clkState = HIGH; | ||
} | ||
|
||
// dacOutput(long) - deal with the DAC output | ||
// ------------------------------------------ | ||
void dacOutput(long v) | ||
{ | ||
// feed this routine a value between 0 and 255 and teh DAC | ||
// output will send it out. | ||
int tmpVal = v; | ||
for (int i=0; i<8; i++) { | ||
digitalWrite(pinOffset + i, tmpVal & 1); | ||
tmpVal = tmpVal >> 1; | ||
} | ||
} | ||
|
||
|
||
// This routine was taken from the Ardcore Oscillator example | ||
// and it's supposed to be faster than dacOutput | ||
void dacOutputFast(long v) | ||
{ | ||
int tmpVal = v; | ||
bitWrite(PORTD, 5, tmpVal & 1); | ||
bitWrite(PORTD, 6, (tmpVal & 2) > 0); | ||
bitWrite(PORTD, 7, (tmpVal & 4) > 0); | ||
bitWrite(PORTB, 0, (tmpVal & 8) > 0); | ||
bitWrite(PORTB, 1, (tmpVal & 16) > 0); | ||
bitWrite(PORTB, 2, (tmpVal & 32) > 0); | ||
bitWrite(PORTB, 3, (tmpVal & 64) > 0); | ||
bitWrite(PORTB, 4, (tmpVal & 128) > 0); | ||
} | ||
|
||
|
||
// deJitter(int, int) - smooth jitter input | ||
// ---------------------------------------- | ||
int deJitter(int v, int test) | ||
{ | ||
// this routine just make sure we have a significant value | ||
// change before we bother implementing it. This is useful | ||
// for cleaning up jittery analog inputs. | ||
if (abs(v - test) > 8) { | ||
return v; | ||
} | ||
return test; | ||
} | ||
|
||
|
||
|
||
// ===================== end of program ======================= |
Oops, something went wrong.