├── Class-1 ├── dg_class1_-_1_analogRead_digitalWrite │ └── dg_class1_-_1_analogRead_digitalWrite.ino ├── dg_class1_-_2_Blink_two_LEDS │ └── dg_class1_-_2_Blink_two_LEDS.ino ├── dg_class1_-_3_digitalRead │ └── dg_class1_-_3_digitalRead.ino ├── dg_class1_-_4_analogWrite │ └── dg_class1_-_4_analogWrite.ino ├── dg_class1_-_5_sound │ └── dg_class1_-_5_sound.ino └── dg_class1_-_6_better_sound │ └── dg_class1_-_6_better_sound.ino ├── Class-2 ├── bleep_base_controls_quick_start │ ├── bleep_base.h │ └── bleep_base_controls_quick_start.ino ├── first_code_1 │ ├── bleep_base.h │ └── first_code_1.ino ├── first_code_2 │ ├── bleep_base.h │ └── first_code_2.ino ├── first_code_3_w_buttons │ ├── bleep_base.h │ └── first_code_3_w_buttons.ino ├── first_code_4_array_sequence │ ├── bleep_base.h │ └── first_code_4_array_sequence.ino ├── first_code_5_random_sequence │ ├── bleep_base.h │ └── first_code_5_random_sequence.ino └── ground_floor_code │ ├── bleep_base.h │ └── ground_floor_code.ino ├── Class-3 ├── Audio_basic_code │ ├── Audio_basic_code.ino │ └── bleep_base.h ├── Audio_basic_code_w_control_1 │ ├── Audio_basic_code_w_control_1.ino │ └── bleep_base.h ├── Audio_basic_code_w_control_2 │ ├── Audio_basic_code_w_control_2.ino │ └── bleep_base.h ├── Audio_basic_code_w_delay_1 │ ├── Audio_basic_code_w_delay_1.ino │ └── bleep_base.h ├── Audio_basic_code_w_delay_2 │ ├── Audio_basic_code_w_delay_2.ino │ └── bleep_base.h └── Audio_basic_code_w_delay_and_AM │ ├── Audio_basic_code_w_delay_and_AM.ino │ └── bleep_base.h ├── Class-4 ├── Class_4_-_Envelope_1 │ ├── Class_4_-_Envelope_1.ino │ └── bleep_base.h ├── Class_4_-_Envelope_2 │ ├── Class_4_-_Envelope_2.ino │ └── bleep_base.h ├── Class_4_-_Envelope_3_w_all_keys │ ├── Class_4_-_Envelope_3_w_all_keys.ino │ └── bleep_base.h ├── Class_4_-_Envelope_4_w_delay │ ├── Class_4_-_Envelope_4_w_delay.ino │ └── bleep_base.h └── Class_4_-_Envelope_5_w_crush │ ├── Class_4_-_Envelope_5_w_crush.ino │ └── bleep_base.h ├── Class-5 ├── class_5_-_8x_sine_waves │ ├── bleep_base.h │ └── class_5_-_8x_sine_waves.ino ├── class_5_-_drum_seq │ ├── bleep_base.h │ └── class_5_-_drum_seq.ino ├── class_5_-_melody1 │ ├── bleep_base.h │ └── calss_5_-_melody1 │ │ └── calss_5_-_melody1.ino ├── class_5_-_melody2_random_steps │ ├── bleep_base.h │ └── class_5_-_melody2_random_steps.ino ├── class_5_-_melody3_change_waveforms │ ├── bleep_base.h │ └── class_5_-_melody3_change_waveforms.ino ├── class_5_-_melody4_now_with_melody │ ├── bleep_base.h │ └── class_5_-_melody4_now_with_melody.ino ├── class_5_-_melody5_now_with_modes │ ├── bleep_base.h │ └── class_5_-_melody5_now_with_modes.ino ├── class_5_-_melody6_with_leds │ ├── bleep_base.h │ └── class_5_-_melody6_with_leds.ino └── smoothing_example_re_Marcel │ ├── bleep_base.h │ └── smoothing_example_re_Marcel.ino ├── Class-6 ├── class_6_-_input_with_AM_and_filters-_commented │ ├── bleep_base.h │ └── class_6_-_input_with_AM_and_filters-_commented.ino ├── class_6_-_melody7-_commented │ ├── bleep_base.h │ └── class_6_-_melody7-_commented.ino ├── class_6_-_oscillators_into_filters_-_commented │ ├── bleep_base.h │ └── class_6_-_oscillators_into_filters_-_commented.ino └── class_6_map_simple_example │ ├── bleep_base.h │ └── class_6_map_simple_example.ino ├── Class-7 ├── MIDI_examples │ ├── MIDI_examples.ino │ └── bleep_base.h ├── MIDI_examples_with_basic_synth │ ├── MIDI_examples_with_basic_synth.ino │ └── bleep_base.h ├── filter_modulation_examples │ ├── bleep_base.h │ └── filter_modulation_examples.ino ├── mapping_and_expo │ ├── bleep_base.h │ └── mapping_and_expo.ino ├── more_leds │ ├── bleep_base.h │ └── more_leds.ino ├── serial_flash_sampler_bleep_base │ ├── bleep_base.h │ ├── sampler2.cpp │ ├── sampler2.h │ ├── sampler_helpers2.h │ └── serial_flash_sampler_bleep_base.ino ├── serial_flash_sampler_bleep_base_kinda_granular_1 │ ├── bleep_base.h │ ├── sampler2.cpp │ ├── sampler2.h │ ├── sampler_helpers2.h │ └── serial_flash_sampler_bleep_base_kinda_granular_1.ino └── tape_delay_example_for_bleep_base │ ├── bleep_base.h │ ├── effect_tape_delay.cpp │ ├── effect_tape_delay.h │ └── tape_delay_example_for_bleep_base.ino ├── Class-8 ├── bleep_base_drone_2 │ ├── bleep_base.h │ ├── bleep_base_drone_2.ino │ ├── effect_tape_delay.cpp │ └── effect_tape_delay.h ├── bleep_base_drum_machine_1 │ ├── bleep_base.h │ ├── bleep_base_drum_machine_1.ino │ ├── mem_sampler.cpp │ ├── mem_sampler.h │ └── samples.h └── poly_example_1 │ ├── bleep_base.h │ └── poly_example_1.ino ├── README.md ├── docs ├── Bleep base v1.dch ├── Bleep base v1.dip ├── Bleep-base-v1-schematic.jpg ├── Class 1 notes - Basic hardware.pdf ├── audio-adapter-dc-couple.png ├── audio_array.jpg ├── bleep_base_header.jpg ├── bleepbase_overhead.png ├── example-1.png ├── flashchip.jpg ├── sample_tab.jpg ├── uno-and-teensy.png └── wav2sketch-browser.jpg └── extras ├── granular_example ├── bleep_base.h └── granular_example.ino ├── granular_example_with_vca_mod ├── bleep_base.h └── granular_example_with_vca_mod.ino ├── photocell_calibrate_example ├── bleep_base.h └── photocell_calibrate_example.ino └── poly_example_1 ├── bleep_base.h └── poly_example_1.ino /Class-1/dg_class1_-_1_analogRead_digitalWrite/dg_class1_-_1_analogRead_digitalWrite.ino: -------------------------------------------------------------------------------- 1 | //This code uses a potentiometer to control the rate of a blinking LED 2 | 3 | //Two slashes means "comment". Anything written after the "//" is ignored by the compiler, the program that turns this code into something the Teensy can use 4 | /* 5 | This has the same effect 6 | */ 7 | //Empty lines are irrelevant. You can have as many or few as you'd like. 8 | 9 | 10 | //This area at the top of our "sketch" is the initialization section 11 | // The first thing we need to do is name the variables we 12 | // want to store values in and decide on the data type 13 | 14 | //"int" stands for integer. It describes a data type which allows the variable 15 | // to be a whole number from -32,767 to 32,767 (16 bits) 16 | int led_pin = 10; // The pin the LED is connected to 17 | int led_state = 0; // The state of LED. 18 | // Pretty much all lines of code end in a semicolon 19 | 20 | //"unsigned long" is another data type that's 32 bits, all of them positive. 0 - 4,294,967,295 21 | // We'll be counting milliseconds with this so the number will get big pretty quickly 22 | unsigned long previous_time = 0; // will store the last time the LED was updated 23 | unsigned long current_time; //will store how much time has elapsed since the Teensy was reset 24 | // if you don't set it equal to a number it will be 0 by default. 25 | 26 | unsigned long rate; //how fast the LED will change 27 | int pot_value; //store the reading from the potentiometer aka knob 28 | int pot_pin = A0; //pins that start with A can do analog readings 29 | 30 | 31 | //This next part is where the code really begins. It runs just once after the Teensy resets. 32 | 33 | void setup() { //The setup starts with this curly bracket here 34 | // Set the LED pin as an output 35 | pinMode(led_pin, OUTPUT);//This function has two inputs. The pin and the state we want it to be https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/ 36 | 37 | //you don't need to setup the pot pin as an input 38 | 39 | } //Setup is over. curly brackets begin and end sections of code. 40 | 41 | 42 | // This part of the code will start as soon as the setup is done and run over and over again 43 | // as fast as the Teensy can go, executing each line in order, one at a time 44 | void loop() 45 | { 46 | //Calls the function "millis". https://www.arduino.cc/reference/en/language/functions/time/millis/ 47 | // It returns the time in milliseconds that have elapsed since the device restarted 48 | // which we store in the variable "current_time" 49 | // That means for the rest or this loop "current_time" will be equal to that number 50 | current_time = millis(); 51 | 52 | pot_value = analogRead(A0); //Read the analog voltage at pin A0. Returns 0 for 0 Volts and 1023 for the max voltage (3.3V) 53 | rate = (pot_value * 2) + 10; //Math! rate is now equal to pot_value times 2 plus 10 54 | 55 | //This next bit of code is something we'll use over and over to control how ofter something happens 56 | // Has "rate" amount of time past since we last executed the code contained in these curly brackets? 57 | // "if" the current time minus the previous time is bigger that the rate then the code inside the curly brackets will run 58 | // If not then it doesn't run it and we continue on to the next thing below the curly brackets 59 | 60 | //We're using milliseconds so a value of 1000 would make it turn on for 1 seconds then off for one 61 | if (current_time - previous_time > rate) { //if begins 62 | previous_time = current_time; //remember what time it is so we can check how long it's been since we executed the code inside the curlys 63 | 64 | // if the LED is off turn it on and vice versa: 65 | if (led_state == 0) { // "==" means check if these values are the same 66 | led_state = 1; // "=" means set the first variable equal to the second value 67 | } 68 | else { //if the previous comparison is not true do this 69 | led_state = 0; 70 | } 71 | 72 | //Output the value "led1_state" to "led1_pin. 73 | // if "led1_state" is low aka "0" the LED will be off 74 | // if "led1_state" is high aka "1" the LED will be on 75 | // it's digital so it can only be on or off which you right as 1 or 0. HIGH or LOW can also be used. 76 | digitalWrite(led_pin, led_state); 77 | 78 | } // the "if" statement is now over. 79 | 80 | } // loop is over so we go back to the start of it with basically no wait 81 | -------------------------------------------------------------------------------- /Class-1/dg_class1_-_2_Blink_two_LEDS/dg_class1_-_2_Blink_two_LEDS.ino: -------------------------------------------------------------------------------- 1 | //If we want a second LED we need to have separate variables for some things 2 | 3 | //Variables will not have anything inherently in common because of their names. We could name them anything. 4 | // The variable names are only there to help us. The compiler gets rid of the names 5 | 6 | // "int" describes a data type which allows the variable to be a whole number from -32,767 to 32,767 (16 bits) 7 | int led1_pin = 10; // The LED1 is attached to 8 | int led1_state = 0; // The state of LED1 9 | 10 | int led2_pin = 9; // The LED2 pin 11 | int led2_state = 0; // The LED2 state 12 | 13 | //"unsigned long" is another data type that's 32 bits, all of them positive. 0 - 4,294,967,295 14 | unsigned long previous_time1 = 0; // will store the last time LED1 was updated 15 | unsigned long previous_time2 = 0; // will store the last time LED2 was updated 16 | unsigned long current_time; //will store how much time has elapsed since the Teensy was reset 17 | // if you don't set it to a number it will be 0 by default. 18 | 19 | unsigned long rate1; //how fast the LED1 will change 20 | unsigned long rate2 = 250; //how fast the LED2 will change 21 | //We can set the variable to a value here and not change it in the loop 22 | 23 | int pot_value; //store the reading from the potentiometer aka knob 24 | int pot_pin = A0; //pins that can do analog readings start with A 25 | 26 | 27 | //This next part is where the code really begins. It runs just once after the Teensy resets. 28 | 29 | void setup() { //The setup starts with this curry bracket here 30 | // set both LED pins as outputs 31 | pinMode(led1_pin, OUTPUT); 32 | pinMode(led2_pin, OUTPUT); 33 | 34 | //you don't need to setup the pot pin as an input 35 | 36 | } //Setup is over. curly brackets begin and end sections of code. 37 | 38 | 39 | // This part of the code will run over and over again as fast as the Teensy can go, 40 | // executing each line in order, one at a time 41 | void loop() 42 | { 43 | //Calls the function "millis". See info on all the basic functions here https://www.arduino.cc/reference/en/ 44 | // It returns the time in milliseconds that have elapsed since the device restarted which we store in the varible "current_time" 45 | // That means for the rest or this loop "current_time" will be equal to that number 46 | current_time = millis(); 47 | 48 | 49 | pot_value = analogRead(pot_pin); //Read the analog voltage at the pin. Returns 0 for 0 Volts and 1023 for the max voltage (3.3V) 50 | rate1 = (pot_value * 2) + 10; //we can do any math on variables you can imagine. 51 | 52 | //Has "rate1" amount of time past since we last executed this code contained in the curly brackets? 53 | // If the current time minus the last time is bigger that the interval then this part of the code is run 54 | // If not then it doesn't and we do the next thing below the curly brackets 55 | //We're using milliseconds so a value of 1000 would make it turn on for 1 seconds then off for one 56 | 57 | if (current_time - previous_time1 > rate1) { 58 | previous_time1 = current_time; //if the statement is true remember the current time 59 | 60 | // if the LED is off turn it on and vice versa: 61 | if (led1_state == LOW) { 62 | led1_state = HIGH; 63 | } 64 | else { 65 | led1_state = LOW; 66 | } 67 | /* 68 | // This wouldn't work. Why not? 69 | if (led1_state == LOW) { 70 | led1_state = HIGH; 71 | } 72 | if (led1_state == HIGH) { 73 | led1_state = LOW; 74 | } 75 | */ 76 | digitalWrite(led1_pin, led1_state); // Write the value "led1_state" to the pin "led1_pin". 77 | } 78 | 79 | 80 | if (current_time - previous_time2 > rate2) { //has "rate2" amount of time past since we last executed this code? 81 | previous_time2 = current_time; 82 | 83 | // if LED2 is off turn it on and vice versa: 84 | if (led2_state == LOW) { //you might see examples written this way. it's the same as 0 and 1 85 | led2_state = HIGH; 86 | } 87 | else { 88 | led2_state = LOW; 89 | } 90 | 91 | digitalWrite(led2_pin, led2_state); // Write the value "led2_state" to "led2_pin. 92 | 93 | } 94 | 95 | } // Loop is over so it starts again with basically no wait 96 | -------------------------------------------------------------------------------- /Class-1/dg_class1_-_3_digitalRead/dg_class1_-_3_digitalRead.ino: -------------------------------------------------------------------------------- 1 | //Using a button to change how the LED blinks 2 | 3 | //Variables will not have anything inherently in common because of their names. We could name them anything. 4 | // The variable names are only there to help us. The compiler gets rid of the names 5 | 6 | // "int" describes a data type which allows the variable to be a whole number from -32,767 to 32,767 (16 bits) 7 | int led1_pin = 10; // The pin for LED1 8 | int led1_state = 0; // The state of LED1 9 | 10 | int led2_pin = 9; // The LED2 pin 11 | int led2_state = 0; // The LED2 state 12 | 13 | //"unsigned long" is another data type that's 32 bits, all of them positive. 0 - 4,294,967,295 14 | unsigned long previous_time1 = 0; // will store the last time LED1 was updated 15 | unsigned long previous_time2 = 0; // will store the last time LED2 was updated 16 | unsigned long current_time; //will store how much time has elapsed since the Teensy was reset 17 | // if you don't set it to a number it will be 0 by default. 18 | 19 | unsigned long rate1; //how fast the LED1 will change 20 | unsigned long rate2 = 250; //how fast the LED2 will change 21 | //We can set the variable to a value here and not change it in the loop 22 | 23 | int pot_value; //store the reading from the potentiometer aka knob 24 | int pot_pin = A0; //pins that can do analog readings start with A 25 | 26 | int button_reading; 27 | int button_pin = 5; //any pin can read a button 28 | 29 | //This next part is where the code really begins. It uns just once after the Teensy resets. 30 | 31 | void setup() { //The setup starts with this currly bracket here 32 | // Set the LED pin as an output 33 | // set both LED pins as outputs 34 | pinMode(led1_pin, OUTPUT); 35 | pinMode(led2_pin, OUTPUT); 36 | pinMode(button_pin, INPUT_PULLUP); //must be done for button pins. It makes the default state for the pin HIGH and 1 37 | 38 | //you don't need to setup the pot pin as an input 39 | 40 | } //Setup is over. curly brackets begin and end sections of code. 41 | 42 | 43 | // This part of the code will run over and over again as fast as the Teensy can go, 44 | // executing each line in order, one at a time 45 | void loop() 46 | { 47 | //Calls the function "millis". See info on all the basic functions here https://www.arduino.cc/reference/en/ 48 | // It returns the time in milliseconds that have elapsed since the device restarted which we store in the varible "current_time" 49 | // That means for the rest or this loop "current_time" will be equal to that number 50 | current_time = millis(); 51 | 52 | 53 | 54 | pot_value = analogRead(pot_pin); //Read the analog voltage at the pin. Returns 0 for 0 Volts and 1023 for the max voltage (3.3V) 55 | rate1 = (pot_value * 2) + 10; //we can do any math on variables you can imagine. 56 | 57 | button_reading = digitalRead(button_pin); //read the status of button pin. Is it 0V or 3.3V. 58 | if (button_reading == 0) { //0 is pressed, 1 is not 59 | rate1 = rate1 / 8; // make it blink 8 times faster if the button is down. 60 | } 61 | 62 | //Has "rate1" amount of time past since we last executed this code contained in the curly brackets? 63 | // If the current time minus the last time is bigger that the interval then this part of the code is run 64 | // If not then it doesn't and we do the next thing below the curly brackets 65 | //We're using milliseconds so a value of 1000 would make it turn on for 1 seconds then off for one 66 | 67 | if (current_time - previous_time1 > rate1) { //has "rate1" amount of time past since we last executed this code? 68 | previous_time1 = current_time; //if the statement is true remember the current time 69 | 70 | // if the LED is off turn it on and vice versa: 71 | if (led1_state == LOW) { 72 | led1_state = HIGH; 73 | } 74 | else { 75 | led1_state = LOW; 76 | } 77 | /* 78 | // This wouldn't work. Why not? 79 | if (led1_state == LOW) { 80 | led1_state = HIGH; 81 | } 82 | if (led1_state == HIGH) { 83 | led1_state = LOW; 84 | } 85 | */ 86 | digitalWrite(led1_pin, led1_state); // Write the value "led1_state" to the pin "led1_pin". 87 | } 88 | 89 | 90 | if (current_time - previous_time2 > rate2) { //has "rate2" amount of time past since we last executed this code? 91 | previous_time2 = current_time; 92 | 93 | // if LED2 is off turn it on and vice versa: 94 | if (led2_state == LOW) { //you might see examples written this way. it's the same as 0 and 1 95 | led2_state = HIGH; 96 | } 97 | else { 98 | led2_state = LOW; 99 | } 100 | 101 | digitalWrite(led2_pin, led2_state); // Write the value "led2_state" to "led2_pin. 102 | 103 | } 104 | 105 | } // Loop is over so it starts again with basically no wait 106 | -------------------------------------------------------------------------------- /Class-1/dg_class1_-_4_analogWrite/dg_class1_-_4_analogWrite.ino: -------------------------------------------------------------------------------- 1 | //Have the LED fade rather than just be on or off 2 | 3 | //Variables will not have anything inherently in common because of their names. We could name them anything. 4 | // The variable names are only there to help us. The compiler gets rid of the names 5 | 6 | // "int" describes a data type which allows the variable to be a whole number from -32,767 to 32,767 (16 bits) 7 | int led1_pin = 9; //For the examples on Feb 1st I'm using a Teensy 3.2 as I'm all out of 4.0s. On the 3.2 only some pins are PWMable https://www.pjrc.com/teensy/pinout.html 8 | int led1_brightness; 9 | int led2_pin = 10; 10 | int led2_brightness; 11 | 12 | //"unsigned long" is another data type that's 32 bits, all of them positive. 0 - 4,294,967,295 13 | unsigned long previous_time1 = 0; // will store the last time LED1 was updated 14 | unsigned long previous_time2 = 0; // will store the last time LED2 was updated 15 | unsigned long current_time; //will store how much time has elapsed since the Teensy was reset 16 | // if you don't set it to a number it will be 0 by default. 17 | 18 | unsigned long rate1; //how fast the LED1 will change 19 | unsigned long rate2 = 250; //how fast the LED2 will change 20 | //We can set the variable to a value here and not change it in the loop 21 | 22 | int pot_value; //store the reading from the potentiometer aka knob 23 | int pot_pin = A0; //pins that can do analog readings start with A 24 | 25 | 26 | void setup() { 27 | // set both LED pins as outputs 28 | pinMode(led1_pin, OUTPUT); 29 | pinMode(led2_pin, OUTPUT); 30 | //you don't need to setup the pot pin as an input 31 | } 32 | 33 | 34 | void loop() 35 | { 36 | current_time = millis(); 37 | 38 | pot_value = analogRead(A0); //Read the analog voltage at pin A0. Returns 0 for 0 Volts and 1023 for the max voltage (3.3V) 39 | rate1 = (pot_value / 100); //we need the rate to go much more quickly 40 | rate2 = rate1 * 3; 41 | 42 | if (current_time - previous_time1 > rate1) { //has "rate1" amount of time past since we last executed this code? 43 | previous_time1 = current_time; //if the statement is true remember the current time 44 | 45 | led1_brightness++; //this is the same as saying... 46 | //led1_brightness=led1_brightness+1 47 | if (led1_brightness > 255) { //analogWrite aka PWM is 0-255, 8 bits 48 | led1_brightness = 0; 49 | } 50 | analogWrite(led1_pin, led1_brightness); // Write the value "led1_brightness" to the pin "led1_pin". 51 | } 52 | 53 | 54 | if (current_time - previous_time2 > rate2) { //has "rate2" amount of time past since we last executed this code? 55 | previous_time2 = current_time; 56 | 57 | led2_brightness++; 58 | if (led2_brightness > 255) {//PWM is 0-255, 8 bits 59 | led2_brightness = 0; 60 | } 61 | 62 | analogWrite(led2_pin, led2_brightness); 63 | 64 | } 65 | 66 | } // Loop is over so it starts again with basically no wait 67 | -------------------------------------------------------------------------------- /Class-1/dg_class1_-_5_sound/dg_class1_-_5_sound.ino: -------------------------------------------------------------------------------- 1 | //blinking is just slow oscillation. Lets make it into something we can hear 2 | 3 | int led1_pin = 10; 4 | int led1_state = 0; 5 | 6 | int led2_pin = 9; 7 | int led2_state = 0; 8 | 9 | int audio_pin = 20; 10 | int audio_state = 0; 11 | 12 | unsigned long previous_time1; //Initializing a variable without saying "=" defaults it to 0 13 | unsigned long previous_time2; 14 | unsigned long previous_time3; 15 | 16 | unsigned long current_time; 17 | 18 | unsigned long rate1; 19 | unsigned long rate2; 20 | unsigned long rate3; 21 | 22 | int button_pin; 23 | int button_state; 24 | 25 | int pot_value; 26 | int pot_pin = A0; 27 | 28 | void setup() { 29 | pinMode(led1_pin, OUTPUT); 30 | pinMode(led2_pin, OUTPUT); 31 | pinMode(audio_pin, OUTPUT); 32 | pinMode(button_pin, INPUT_PULLUP); 33 | //analog inputs do not need to be setup 34 | } 35 | 36 | void loop() 37 | { 38 | current_time = millis(); 39 | 40 | button_state = digitalRead(button_pin); //if the button is not being pressed it will read 1. if it pressed it will read 0 41 | 42 | pot_value = analogRead(pot_pin); //Read the analog voltage at pin A0. Returns 0 for 0 Volts and 1023 for the max voltage (3.3V) 43 | rate1 = pot_value / 2; 44 | rate2 = pot_value / 5; 45 | rate3 = pot_value / 10; 46 | 47 | 48 | if (current_time - previous_time1 > rate1) { 49 | previous_time1 = current_time; 50 | 51 | if (led1_state == LOW) { 52 | led1_state = HIGH; 53 | } 54 | else { 55 | led1_state = LOW; 56 | } 57 | digitalWrite(led1_pin, led1_state); 58 | } 59 | 60 | 61 | if (current_time - previous_time2 > rate2) { 62 | previous_time2 = current_time; 63 | 64 | if (led2_state == 0) { 65 | led2_state = 1; 66 | } 67 | else { 68 | led2_state = 0; 69 | } 70 | digitalWrite(led2_pin, led2_state); 71 | } 72 | 73 | if (current_time - previous_time3 > rate3) { 74 | previous_time3 = current_time; 75 | 76 | if (audio_state == 0) { 77 | audio_state = 1; 78 | } 79 | else { 80 | audio_state = 0; 81 | } 82 | digitalWrite(audio_pin, audio_state); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Class-1/dg_class1_-_6_better_sound/dg_class1_-_6_better_sound.ino: -------------------------------------------------------------------------------- 1 | /* 2 | It's a big leap from making sound we way we did before to something that sounds like a "real" synth 3 | You can only ever do one thing at a time on any computer and you can pretty much only do it at one speed. 4 | The Teensy 4.0 can do a simple operation hundreds of millions of times a seconds. Things take a lot of little operations to do but still it's fast 5 | but what if you want a light blinking at something faster than 1 millisecond but slower than 150MHz? https://forum.pjrc.com/threads/57185-Teensy-4-0-Bitbang-FAST 6 | 7 | You can interrupt the loop after a set amount of micro or even nano seconds have passed. We can kind of thinking this like multitasking 8 | the loop is still looping but ever X nano seconds it stops what it's doing and does the things that have in the interval 9 | 10 | */ 11 | 12 | 13 | IntervalTimer timer1; //Make a new interval timer called timer1 14 | 15 | int led1_pin = 10; 16 | int led1_state = LOW; 17 | int led2_pin = 9; 18 | int led2_state = 0; 19 | unsigned long previous_time1 = 0; 20 | unsigned long previous_time2 = 0; 21 | unsigned long previous_time3 = 0; 22 | unsigned long current_time; 23 | unsigned long interval1 = 50; 24 | unsigned long interval2 = 50; 25 | unsigned long interval3 = 50; 26 | int button_pin; 27 | int button_state; 28 | int pot1_value; 29 | int pot1_pin = A0; 30 | int pot2_value; 31 | int pot2_pin = A1; 32 | float volume_pot; //floats can hold decimals 33 | float freq1; 34 | float freq2; 35 | int out1, out2, out3;// You can define variables like this too. All of them will be integers equal to 0 36 | uint32_t dds_tune; 37 | uint32_t dds_rate; 38 | 39 | void setup() { 40 | pinMode(led1_pin, OUTPUT); 41 | pinMode(led2_pin, OUTPUT); 42 | pinMode(button_pin, INPUT_PULLUP); 43 | 44 | analogWriteResolution(8); //we can make this up to 12 bits but it won't really help us with better quality audio and blinky LEDs 45 | analogWriteFrequency(20, 187500); //set the PWM rate well above the audio rage to limit noise 46 | 47 | //set the rate of our interrupt timer 48 | dds_rate = 20; //20 microseconds = 50KHz 49 | dds_tune = (1.00 / (dds_rate * .000001)); //used to make the oscillation at the frequency we want them to be 50 | timer1.begin(osc1, dds_rate); 51 | 52 | } 53 | 54 | void osc1() { // code that is run whenever the timer goes off, every 20 micros 55 | //these functions are not hidden away like the onces we've used so far. They are at the bottom of this code 56 | out1 = oscillator(0, freq1, 1, .5); //oscillator(voice select, frequency, amplitude, shape) 57 | out2 = oscillator(1, freq2, 1, .3); // More info on how this works at the bottom of the code 58 | out3 = fold((out1 + out2) * volume_pot); //folds the input instead of clipping it based on the level of the volume pot. 59 | 60 | analogWrite(20, (out3 + 2048) >> 4); // The oscillators produce numbers between -2048 and 2048 but the DAC can't output negative numbers so we add the offset back in 61 | // >> is bit shifting and is much faster than dividing. The oscillator is 12 bit resolution but we're outputting 8 62 | } 63 | 64 | void loop() 65 | { 66 | //everything happens like normal in the loop it just takes a little longer to finish, but only like milliseconds longer. 67 | current_time = millis(); 68 | 69 | button_state = digitalRead(button_pin); //if the button is not being pressed it will read HIGH. if it pressed it will read LOW 70 | 71 | pot1_value = analogRead(pot1_pin); //Read the analog voltage at pin A0. Returns 0 for 0 volts and 1023 for the max voltage (3.3V) 72 | interval1 = pot1_value / 2; //these aren't floats so we basically loose the remainders but it's not a critical setting. 73 | interval2 = pot1_value / 5; 74 | freq1 = pot1_value / 2.0; //divide by a float to make sure we get a float out 75 | freq2 = freq1 * .501; //have the second oscillator be an octave lower than the first but a little detuned 76 | 77 | pot2_value = analogRead(pot2_pin) / 4; //analogRead returns 0-1024 but analogWrite is 0-255 so we divide by 4. 10 bits to 8 bits. We'll talk about these funny numbers later 78 | volume_pot = (analogRead(pot2_pin) / 1023.00) * 8.0; //Take the reading, make it from 0.0 to 1.0, then multiply to get 0.0 to 8.0 79 | 80 | if (current_time - previous_time1 > interval1) { 81 | previous_time1 = current_time; 82 | 83 | if (led1_state == LOW) { 84 | led1_state = HIGH; 85 | } 86 | else { 87 | led1_state = LOW; 88 | } 89 | analogWrite(led1_pin, led1_state * pot2_value); //since the state is 1 or 0 it's off half the time, on at our new pot reading the other half 90 | } 91 | 92 | 93 | if (current_time - previous_time2 > interval2) { 94 | previous_time2 = current_time; 95 | 96 | if (led2_state == 0) { 97 | led2_state = 1; 98 | } 99 | else { 100 | led2_state = 0; 101 | } 102 | analogWrite(led2_pin, led2_state * pot2_value); 103 | } 104 | } 105 | 106 | //you can declare "global" variable wherever but the code above it can't see them. 107 | // This is why you should usually do your declaring at the very top 108 | // I put all this down here as only the oscillator function needs these variables and to avoid confusion at the top. 109 | int wavelength = 4095; 110 | unsigned long accumulator[8] = {}; //these are arrays here where are 8 separate variables called accumulator. accumulator[0],accumulator[1],etc 111 | unsigned long increment[8] = {}; 112 | unsigned long waveindex[8] = {}; 113 | 114 | 115 | //Here's a function I made to generate a waveform that can be adjusted from saw to ramp 116 | 117 | //(voice select, frequency, amplitude, shape) 118 | // Each separate oscillator needs a unique voice select number 119 | // Frequency is a floating point to allow for finer control 120 | // Amplitude is a float 0.0 to 1.0, off to full amplitude 121 | // 0.0 shape is a saw, 0.5 is triangle and 1.0 is ramp 122 | 123 | int oscillator(byte sel, float freq, float amp, float tri_shape) { 124 | int tout; //"local" variables can only be seen in the {} they are in and anything in sub {} 125 | int waveamp = amp * 4095.00; 126 | 127 | int knee = tri_shape * 4095.00; 128 | 129 | if (knee < 0) 130 | { 131 | knee = 0; 132 | } 133 | 134 | if (knee > wavelength - 1) 135 | { 136 | knee = wavelength - 1; 137 | } 138 | 139 | //basic DDS http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/index.html 140 | increment[sel] = (4294967296.00 * (freq)) / (dds_tune); //(2^32) * the frequency we want to output divided buy the calculation we made up in setup. Gives 32 bits of frequency resolution 141 | 142 | accumulator[sel] += increment[sel]; 143 | waveindex[sel] = ((accumulator[sel]) >> (32 - 12)); //wavelength is 12 bits 144 | 145 | if (waveindex[sel] < knee) { 146 | tout = ((waveindex[sel]) * waveamp) / knee; 147 | } 148 | 149 | if (waveindex[sel] >= knee) { 150 | tout = ((((waveindex[sel] - knee) * waveamp) / (wavelength - knee)) * -1) + waveamp; 151 | } 152 | 153 | return tout - (waveamp / 2); //output a signal that goes from -2048 to 2048 154 | 155 | } 156 | 157 | //This is meant to "fold" a waveform, creating new harmonics 158 | // just give it an input and it returns a folded output 159 | int fold(int input) { 160 | int foldv = input; 161 | 162 | int h_res = 2040; 163 | int ih_res = h_res * -1; 164 | 165 | for (int i = 0; i < 8; i++) { 166 | if (foldv > h_res) { 167 | foldv -= ((foldv - h_res) * 2); 168 | } 169 | if (foldv < ih_res) { 170 | foldv += ((foldv * -1) - (h_res)) * 2; 171 | } 172 | } 173 | return foldv; 174 | } 175 | -------------------------------------------------------------------------------- /Class-2/bleep_base_controls_quick_start/bleep_base_controls_quick_start.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | 14 | void setup() { 15 | start_bleep_base(); //run this first in setup 16 | } 17 | 18 | void loop() { 19 | update_controls(); //run this first in the loop 20 | current_time = millis(); //then check the time 21 | 22 | rate1 = potRead(4) * 20; //potRead returns 0-1.0 23 | rate2 = potRead(6) * 20; 24 | 25 | //prev_time[0] is a variable in the first position of the array. in the declaration section we gave it 8 places 26 | if (current_time - prev_time[0] > rate1) { 27 | prev_time[0] = current_time; 28 | lfo1 *= 1.01; 29 | if (lfo1 > 1.0) { 30 | lfo1 = .1; 31 | } 32 | } 33 | 34 | if (current_time - prev_time[1] > rate2) { 35 | prev_time[1] = current_time; 36 | lfo2 *= 1.01; 37 | if (lfo2 > 1.0) { 38 | lfo2 = .1; 39 | } 40 | } 41 | 42 | if (current_time - prev_time[2] > 33) { //33 ms is about 30Hz https://www.wolframalpha.com/input/?i=30Hz+in+milliseconds 43 | prev_time[2] = current_time; 44 | 45 | float h1 = potRead(0); //we can declare new variables but they will only be available to use in inside these {} 46 | float s1 = potRead(1); 47 | float h2 = potRead(2); 48 | float s2 = potRead(3); 49 | 50 | set_LED(0, lfo1, s1, lfo1); //(LED select, hue, saturation, brightness) H S and B are all 0-1.0 51 | set_LED(1, lfo2, s2, lfo2); 52 | LEDs.show(); // after we've set what we want all the LEDs to be we send the data out through this function 53 | } 54 | 55 | //"for" loops the contents in it's {} as long as the condition is true 56 | // int j=0 starts with j =0 57 | // j<8 as long as j is less than 8 keep executing the code inside the "for" 58 | // j++ each time you get to the bottom of the for loop add one to j. Same as j=j+1 59 | for (int j = 0; j < 8; j++) { 60 | 61 | //we have to check if the button rose or fell very quickly. If you put this in a timing if you'll miss it 62 | //FELL is defined as the button was high and now it's low 63 | if (buttonState(j) == FELL) { 64 | //serial print send values from the teesny to your computer and puts them in the serial monitor. 65 | //You can access it in tools>serial monitor, or just by clicking the icon in the top right of the Arduino program 66 | Serial.print(" button "); //print the characters " button " 67 | Serial.print(j); //print the variable j 68 | Serial.println("FELL "); // print "FELL " then a return. "println" is new line 69 | } 70 | 71 | if (buttonState(j) == ROSE) { 72 | Serial.print(" button "); 73 | Serial.print(j); 74 | Serial.println("ROSE "); 75 | } 76 | } //for is over 77 | 78 | 79 | if (current_time - prev_time[3] > 100) { 80 | prev_time[3] = current_time; 81 | if (buttonRead(1) == 0) {//print the values of the lfos ever 100 milliseconds when button 1 is pressed 82 | Serial.print(lfo1); 83 | Serial.print(" "); 84 | Serial.println(lfo2); 85 | } 86 | if (buttonRead(4) == 0) {//print all the pots when button 1 is pressed 87 | for (int j = 0; j < 8; j++) { 88 | Serial.print(potRead(j) * 1000.0); //it's easier to read if it's x 1000 89 | Serial.print(" "); 90 | } 91 | Serial.println(); 92 | } 93 | } 94 | 95 | }// loop is over 96 | -------------------------------------------------------------------------------- /Class-2/first_code_1/first_code_1.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | int rate3 = 33; 14 | float h1; 15 | float h2; 16 | float b1; 17 | float b2; 18 | 19 | void setup() { 20 | start_bleep_base(); //run this first in setup 21 | } 22 | 23 | void loop() { 24 | update_controls(); //run this first in the loop 25 | current_time = millis(); 26 | 27 | if (current_time - prev_time[0] > 30) { 28 | prev_time[0] = current_time; 29 | h1 = potRead(0); 30 | b1 = potRead(1); 31 | set_LED(0, h1, 1.0, b1); 32 | set_LED(1, 0, 0, 0); 33 | LEDs.show(); 34 | } 35 | 36 | 37 | }// loop is over 38 | -------------------------------------------------------------------------------- /Class-2/first_code_2/first_code_2.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | int rate3 = 33; 14 | float h1; 15 | float h2; 16 | float b1; 17 | float b2; 18 | float led_state; 19 | 20 | void setup() { 21 | start_bleep_base(); //run this first in setup 22 | } 23 | 24 | void loop() { 25 | update_controls(); //run this first in the loop 26 | current_time = millis(); 27 | 28 | rate1 = (1.0 - potRead(2)) * 1000.0; 29 | 30 | if (current_time - prev_time[1] > rate1) { 31 | prev_time[1] = current_time; 32 | 33 | if (led_state == 0) { 34 | led_state = 1; 35 | } 36 | else { 37 | led_state = 0; 38 | } 39 | 40 | } 41 | 42 | 43 | if (current_time - prev_time[0] > 30) { 44 | prev_time[0] = current_time; 45 | h1 = potRead(0); 46 | b1 = potRead(1) * led_state; 47 | set_LED(0, h1, 1.0, b1); 48 | set_LED(1, 0, 0, 0); 49 | LEDs.show(); 50 | } 51 | 52 | 53 | }// loop is over 54 | -------------------------------------------------------------------------------- /Class-2/first_code_3_w_buttons/first_code_3_w_buttons.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | float h1; 14 | float h2; 15 | float b1; 16 | float b2; 17 | float led_state; 18 | 19 | void setup() { 20 | start_bleep_base(); //run this first in setup 21 | } 22 | 23 | void loop() { 24 | update_controls(); //run this first in the loop 25 | current_time = millis(); //then check the time 26 | 27 | rate1 = potRead(2) * 1000.0; 28 | 29 | if (current_time - prev_time[1] > rate1) { 30 | prev_time[1] = current_time; 31 | 32 | if (led_state == 0) { 33 | led_state = 1; 34 | } 35 | else { 36 | led_state = 0; 37 | } 38 | } 39 | 40 | if (current_time - prev_time[0] > 30) { 41 | prev_time[0] = current_time; 42 | h1 = potRead(0); 43 | b1 = potRead(1) * led_state; 44 | 45 | set_LED(0, h1, 1.0, b1); 46 | set_LED(1, h2, 1.0, b2); 47 | LEDs.show(); 48 | } 49 | 50 | int latch1=0; 51 | for (int j = 0; j < 8; j++) { 52 | if (buttonRead(j) == 0) { 53 | h2=j*(.1); 54 | latch1=1; 55 | } 56 | } 57 | if (latch1==1){ 58 | b2=1.0; 59 | } 60 | else{ 61 | b2=0; 62 | } 63 | 64 | 65 | /* 66 | if (buttonRead(0) == 0) { 67 | h2 = .2; 68 | b2 = 1.0; 69 | } 70 | else { 71 | b2 = 0; 72 | } 73 | if (buttonRead(1) == 0) { 74 | h2 = .4; 75 | b2 = 1.0; 76 | } 77 | else { 78 | b2 = 0; 79 | } 80 | if (buttonRead(2) == 0) { 81 | h2 = .6; 82 | b2 = 1.0; 83 | } 84 | else { 85 | b2 = 0; 86 | } 87 | */ 88 | 89 | 90 | 91 | 92 | 93 | }// loop is over 94 | -------------------------------------------------------------------------------- /Class-2/first_code_4_array_sequence/first_code_4_array_sequence.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | float h1; 14 | float h2; 15 | float b1; 16 | float b2; 17 | float led_state; 18 | int array1[16] = {1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, }; 19 | int array_counter; 20 | 21 | void setup() { 22 | start_bleep_base(); //run this first in setup 23 | } 24 | 25 | void loop() { 26 | update_controls(); //run this first in the loop 27 | current_time = millis(); //then check the time 28 | 29 | rate1 = potRead(2) * 1000.0; 30 | //rate1 = pcellRead() * 1000.0; 31 | 32 | 33 | if (current_time - prev_time[2] > 10) { 34 | prev_time[2] = current_time; 35 | Serial.print(array_counter); 36 | Serial.print(" "); 37 | Serial.print(array1[array_counter]); 38 | Serial.println(); 39 | } 40 | 41 | 42 | if (current_time - prev_time[1] > rate1) { 43 | prev_time[1] = current_time; 44 | 45 | array_counter ++ 46 | if (array_counter > 15) { 47 | array_counter = 0; 48 | } 49 | led_state = array1[array_counter]; 50 | 51 | } 52 | 53 | if (current_time - prev_time[0] > 30) { 54 | prev_time[0] = current_time; 55 | h1 = potRead(0); 56 | b1 = potRead(1) * led_state; 57 | 58 | set_LED(0, h1, 1.0, b1); 59 | set_LED(1, h2, 1.0, b2); 60 | LEDs.show(); 61 | } 62 | 63 | int latch1 = 0; 64 | for (int j = 0; j < 8; j++) { 65 | if (buttonRead(j) == 0) { 66 | h2 = j * (.1); 67 | latch1 = 1; 68 | } 69 | } 70 | 71 | if (latch1 == 1) { 72 | b2 = 1.0; 73 | } 74 | else { 75 | b2 = 0; 76 | } 77 | 78 | 79 | /* 80 | if (buttonRead(0) == 0) { 81 | h2 = .2; 82 | b2 = 1.0; 83 | } 84 | else { 85 | b2 = 0; 86 | } 87 | if (buttonRead(1) == 0) { 88 | h2 = .4; 89 | b2 = 1.0; 90 | } 91 | else { 92 | b2 = 0; 93 | } 94 | if (buttonRead(2) == 0) { 95 | h2 = .6; 96 | b2 = 1.0; 97 | } 98 | else { 99 | b2 = 0; 100 | } 101 | */ 102 | 103 | 104 | 105 | 106 | 107 | }// loop is over 108 | -------------------------------------------------------------------------------- /Class-2/first_code_5_random_sequence/first_code_5_random_sequence.ino: -------------------------------------------------------------------------------- 1 | //bleep base basic controls 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | float h1; 14 | float h2; 15 | float b1; 16 | float b2; 17 | float led_state; 18 | int array1[16] = {1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, }; 19 | int array_counter; 20 | 21 | void setup() { 22 | start_bleep_base(); //run this first in setup 23 | } 24 | 25 | void loop() { 26 | update_controls(); //run this first in the loop 27 | current_time = millis(); //then check the time 28 | 29 | rate1 = potRead(2) * 1000.0; 30 | //rate1 = pcellRead() * 1000.0; 31 | 32 | 33 | if (current_time - prev_time[2] > 10) { 34 | prev_time[2] = current_time; 35 | Serial.print(array_counter); 36 | Serial.print(" "); 37 | Serial.print(array1[array_counter]); 38 | Serial.println(); 39 | } 40 | 41 | 42 | if (current_time - prev_time[1] > rate1) { 43 | prev_time[1] = current_time; 44 | 45 | int r1 = random(0,100); 46 | if (r1>60){ 47 | led_state=1; 48 | } 49 | else{ 50 | led_state=0; 51 | } 52 | 53 | } 54 | 55 | if (current_time - prev_time[0] > 30) { 56 | prev_time[0] = current_time; 57 | h1 = potRead(0); 58 | b1 = potRead(1) * led_state; 59 | 60 | set_LED(0, h1, 1.0, b1); 61 | set_LED(1, h2, 1.0, b2); 62 | LEDs.show(); 63 | } 64 | 65 | int latch1 = 0; 66 | for (int j = 0; j < 8; j++) { 67 | if (buttonRead(j) == 0) { 68 | h2 = j * (.1); 69 | latch1 = 1; 70 | } 71 | } 72 | 73 | if (latch1 == 1) { 74 | b2 = 1.0; 75 | } 76 | else { 77 | b2 = 0; 78 | } 79 | 80 | 81 | /* 82 | if (buttonRead(0) == 0) { 83 | h2 = .2; 84 | b2 = 1.0; 85 | } 86 | else { 87 | b2 = 0; 88 | } 89 | if (buttonRead(1) == 0) { 90 | h2 = .4; 91 | b2 = 1.0; 92 | } 93 | else { 94 | b2 = 0; 95 | } 96 | if (buttonRead(2) == 0) { 97 | h2 = .6; 98 | b2 = 1.0; 99 | } 100 | else { 101 | b2 = 0; 102 | } 103 | */ 104 | 105 | 106 | 107 | 108 | 109 | }// loop is over 110 | -------------------------------------------------------------------------------- /Class-2/ground_floor_code/ground_floor_code.ino: -------------------------------------------------------------------------------- 1 | //use this as your starting point 2 | 3 | //Include means add code from another file. This allows use more functions 4 | #include "bleep_base.h" //must be included at the top 5 | 6 | //then you can declare any variables you want. 7 | unsigned long current_time; 8 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 9 | float lfo1 = 1; //float can contain decimals 10 | float lfo2 = 1; 11 | int rate1; 12 | int rate2; 13 | float h1; 14 | float h2; 15 | float b1; 16 | float b2; 17 | float led_state; 18 | int array1[16] = {1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, }; 19 | int array_counter; 20 | 21 | void setup() { 22 | start_bleep_base(); //run this first in setup 23 | } 24 | 25 | void loop() { 26 | update_controls(); //run this first in the loop 27 | current_time = millis(); //then check the time 28 | 29 | 30 | 31 | }// loop is over 32 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code/Audio_basic_code.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=167,267 17 | AudioSynthWaveform waveform1; //xy=175,215 18 | AudioMixer4 mixer1; //xy=383,245 19 | AudioOutputI2S i2s1; //xy=591,244 20 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 21 | AudioConnection patchCord2(waveform1, 0, mixer1, 0); 22 | AudioConnection patchCord3(mixer1, 0, i2s1, 0); 23 | AudioConnection patchCord4(mixer1, 0, i2s1, 1); 24 | AudioControlSGTL5000 sgtl5000_1; //xy=484,355 25 | // GUItool: end automatically generated code 26 | 27 | 28 | #include "bleep_base.h" //Then we can add this line that we will still need 29 | 30 | //then you can declare any variables you want. 31 | unsigned long current_time; 32 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 33 | 34 | 35 | void setup() { 36 | start_bleep_base(); //run this first in setup 37 | 38 | //there's a lot we need to do in setup now but most of it is just copy paste. 39 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 40 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 41 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 42 | // It's usually the delay and reverb that hog it. 43 | AudioMemory(10); 44 | 45 | sgtl5000_1.enable(); //Turn the adapter board on 46 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 47 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 48 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 49 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 50 | 51 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 52 | // For headphones it's pretty loud at .4 53 | // There are lots of places we can change the final volume level. 54 | // For now lets set this one once and leave it alone. 55 | sgtl5000_1.volume(0.25); 56 | 57 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 58 | // If you're not using the line out don't worry about it. 59 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 60 | 61 | 62 | //This next group can be done anywhere in the code but we want to start things with these 63 | // values and change some of them in the loop. 64 | 65 | //Notice we start by writing the object we want, then a period, then the function 66 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 67 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 68 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 69 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 70 | 71 | //The mixer has four inputs we can change the volume of 72 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 73 | // A gain of 1 means the output is the same as the input. 74 | // .5 would be half volume and 2 would be double 75 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 76 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 77 | mixer1.gain(0, 1); 78 | mixer1.gain(1, 0); 79 | mixer1.gain(2, 0); 80 | mixer1.gain(3, 0); 81 | 82 | } //setup is over 83 | 84 | void loop() { 85 | update_controls(); 86 | current_time = millis(); 87 | 88 | 89 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 90 | if (current_time - prev_time[0] > 500) { 91 | prev_time[0] = current_time; 92 | 93 | //Here we print out the usage of the audio library 94 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 95 | // If you're using too many block, jut increas the number up top untill you're over it by a few 96 | Serial.print("processor: "); 97 | Serial.print(AudioProcessorUsageMax()); 98 | Serial.print("% Memory: "); 99 | Serial.print(AudioMemoryUsageMax()); 100 | Serial.println(); 101 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 102 | AudioMemoryUsageMaxReset(); 103 | } 104 | 105 | }// loop is over 106 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code_w_control_1/Audio_basic_code_w_control_1.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=167,267 17 | AudioSynthWaveform waveform1; //xy=175,215 18 | AudioMixer4 mixer1; //xy=383,245 19 | AudioOutputI2S i2s1; //xy=591,244 20 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 21 | AudioConnection patchCord2(waveform1, 0, mixer1, 0); 22 | AudioConnection patchCord3(mixer1, 0, i2s1, 0); 23 | AudioConnection patchCord4(mixer1, 0, i2s1, 1); 24 | AudioControlSGTL5000 sgtl5000_1; //xy=484,355 25 | // GUItool: end automatically generated code 26 | 27 | 28 | #include "bleep_base.h" //Then we can add this line that we will still need 29 | 30 | //then you can declare any variables you want. 31 | unsigned long current_time; 32 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 33 | float freq1; 34 | float freq2; 35 | float amp1,amp2; 36 | 37 | void setup() { 38 | start_bleep_base(); //run this first in setup 39 | 40 | //there's a lot we need to do in setup now but most of it is just copy paste. 41 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 42 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 43 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 44 | // It's usually the delay and reverb that hog it. 45 | AudioMemory(100); 46 | 47 | sgtl5000_1.enable(); //Turn the adapter board on 48 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 49 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 50 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 51 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 52 | 53 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 54 | // For headphones it's pretty loud at .4 55 | // There are lots of places we can change the final volume level. 56 | // For now lets set this one once and leave it alone. 57 | sgtl5000_1.volume(0.25); 58 | 59 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 60 | // If you're not using the line out don't worry about it. 61 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 62 | 63 | 64 | //This next group can be done anywhere in the code but we want to start things with these 65 | // values and change some of them in the loop. 66 | 67 | //Notice we start by writing the object we want, then a period, then the function 68 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 69 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 70 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 71 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 72 | 73 | //The mixer has four inputs we can change the volume of 74 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 75 | // A gain of 1 means the output is the same as the input. 76 | // .5 would be half volume and 2 would be double 77 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 78 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 79 | mixer1.gain(0, .5); 80 | mixer1.gain(1, .5); 81 | mixer1.gain(2, 0); 82 | mixer1.gain(3, 0); 83 | 84 | } //setup is over 85 | 86 | 87 | void loop() { 88 | update_controls(); 89 | current_time = millis(); 90 | 91 | freq1=(1.0-potRead(0))*1000.0; 92 | //freq1=potRead(0)*1000.0; 93 | waveform1.frequency(freq1); 94 | 95 | freq2=1000.0-(potRead(1)*1000.0); 96 | waveform2.frequency(freq2); 97 | 98 | amp1=potRead(2)*.5; 99 | mixer1.gain(0,amp1); 100 | 101 | amp2=potRead(3)*.5; 102 | mixer1.gain(1,amp2); 103 | 104 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 105 | if (current_time - prev_time[0] > 500) { 106 | prev_time[0] = current_time; 107 | 108 | //Here we print out the usage of the audio library 109 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 110 | // If you're using too many block, jut increas the number up top untill you're over it by a few 111 | Serial.print("processor: "); 112 | Serial.print(AudioProcessorUsageMax()); 113 | Serial.print("% Memory: "); 114 | Serial.print(AudioMemoryUsageMax()); 115 | Serial.println(); 116 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 117 | AudioMemoryUsageMaxReset(); 118 | } 119 | 120 | }// loop is over 121 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code_w_control_2/Audio_basic_code_w_control_2.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform3; //xy=149.00569534301758,227.00566482543945 17 | AudioSynthWaveform waveform4; //xy=166.0056915283203,285.0056838989258 18 | AudioSynthWaveform waveform2; //xy=167.00000190734863,178.99998569488525 19 | AudioSynthWaveform waveform1; //xy=190,133.00000190734863 20 | AudioMixer4 mixer1; //xy=417.9999771118164,188.99998474121094 21 | AudioOutputI2S i2s1; //xy=620.9999599456787,188.99998474121094 22 | AudioConnection patchCord1(waveform3, 0, mixer1, 2); 23 | AudioConnection patchCord2(waveform4, 0, mixer1, 3); 24 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 25 | AudioConnection patchCord4(waveform1, 0, mixer1, 0); 26 | AudioConnection patchCord5(mixer1, 0, i2s1, 0); 27 | AudioConnection patchCord6(mixer1, 0, i2s1, 1); 28 | AudioControlSGTL5000 sgtl5000_1; //xy=496,293 29 | // GUItool: end automatically generated code 30 | 31 | 32 | #include "bleep_base.h" //Then we can add this line that we will still need 33 | 34 | //then you can declare any variables you want. 35 | unsigned long current_time; 36 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 37 | float freq1; 38 | float freq2; 39 | float freq3; 40 | float freq4; 41 | float amp1, amp2, amp3, amp4; 42 | 43 | void setup() { 44 | start_bleep_base(); //run this first in setup 45 | 46 | //there's a lot we need to do in setup now but most of it is just copy paste. 47 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 48 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 49 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 50 | // It's usually the delay and reverb that hog it. 51 | AudioMemory(100); 52 | 53 | sgtl5000_1.enable(); //Turn the adapter board on 54 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 55 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 56 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 57 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 58 | 59 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 60 | // For headphones it's pretty loud at .4 61 | // There are lots of places we can change the final volume level. 62 | // For now lets set this one once and leave it alone. 63 | sgtl5000_1.volume(0.25); 64 | 65 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 66 | // If you're not using the line out don't worry about it. 67 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 68 | 69 | 70 | //This next group can be done anywhere in the code but we want to start things with these 71 | // values and change some of them in the loop. 72 | 73 | //Notice we start by writing the object we want, then a period, then the function 74 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 75 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 76 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 77 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 78 | waveform3.begin(1, 220.0, WAVEFORM_SINE); 79 | waveform4.begin(1, 440.0, WAVEFORM_SINE); 80 | 81 | //The mixer has four inputs we can change the volume of 82 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 83 | // A gain of 1 means the output is the same as the input. 84 | // .5 would be half volume and 2 would be double 85 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 86 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 87 | mixer1.gain(0, .25); 88 | mixer1.gain(1, .25); 89 | mixer1.gain(2, .25); 90 | mixer1.gain(3, .25); 91 | 92 | } //setup is over 93 | 94 | 95 | void loop() { 96 | update_controls(); 97 | current_time = millis(); 98 | 99 | freq1 = (1.0 - potRead(0)) * 1000.0; 100 | //freq1=potRead(0)*1000.0; 101 | waveform1.frequency(freq1); 102 | 103 | freq2 = freq1 * (potRead(1) + 1.0); 104 | waveform2.frequency(freq2); 105 | 106 | freq3 = freq1 * (potRead(2) + 1.0); 107 | waveform3.frequency(freq3); 108 | 109 | freq4 = freq1 * (potRead(3) + 1.0); 110 | waveform4.frequency(freq4); 111 | 112 | 113 | amp1 = potRead(4) * .25; 114 | mixer1.gain(0, amp1); 115 | 116 | amp2 = potRead(5) * .25; 117 | mixer1.gain(1, amp2); 118 | 119 | amp3 = potRead(6) * .25; 120 | mixer1.gain(2, amp3); 121 | 122 | amp4 = potRead(7) * .25; 123 | mixer1.gain(3, amp4); 124 | 125 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 126 | if (current_time - prev_time[0] > 500) { 127 | prev_time[0] = current_time; 128 | 129 | //Here we print out the usage of the audio library 130 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 131 | // If you're using too many block, jut increas the number up top untill you're over it by a few 132 | Serial.print("processor: "); 133 | Serial.print(AudioProcessorUsageMax()); 134 | Serial.print("% Memory: "); 135 | Serial.print(AudioMemoryUsageMax()); 136 | Serial.println(); 137 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 138 | AudioMemoryUsageMaxReset(); 139 | } 140 | 141 | }// loop is over 142 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code_w_delay_1/Audio_basic_code_w_delay_1.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // GUItool: begin automatically generated code 15 | AudioSynthWaveform waveform3; //xy=149.00569534301758,227.00566482543945 16 | AudioSynthWaveform waveform4; //xy=166.0056915283203,285.0056838989258 17 | AudioSynthWaveform waveform2; //xy=167.00000190734863,178.99998569488525 18 | AudioSynthWaveform waveform1; //xy=190,133.00000190734863 19 | AudioMixer4 mixer1; //xy=339.99996757507324,197.99998092651367 20 | AudioEffectDelay delay1; //xy=496.00562286376953,374.0055408477783 21 | AudioMixer4 mixer2; //xy=507.00558853149414,255.00561904907227 22 | AudioMixer4 mixer3; //xy=561.0056991577148,140.00568008422852 23 | AudioOutputI2S i2s1; //xy=744.9999008178711,125.99998760223389 24 | AudioConnection patchCord1(waveform3, 0, mixer1, 2); 25 | AudioConnection patchCord2(waveform4, 0, mixer1, 3); 26 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 27 | AudioConnection patchCord4(waveform1, 0, mixer1, 0); 28 | AudioConnection patchCord5(mixer1, 0, mixer2, 0); 29 | AudioConnection patchCord6(mixer1, 0, mixer3, 0); 30 | AudioConnection patchCord7(delay1, 0, mixer2, 1); 31 | AudioConnection patchCord8(mixer2, delay1); 32 | AudioConnection patchCord9(mixer2, 0, mixer3, 1); 33 | AudioConnection patchCord10(mixer3, 0, i2s1, 0); 34 | AudioConnection patchCord11(mixer3, 0, i2s1, 1); 35 | AudioControlSGTL5000 sgtl5000_1; //xy=716.9999694824219,271.9999809265137 36 | // GUItool: end automatically generated code 37 | 38 | 39 | #include "bleep_base.h" //Then we can add this line that we will still need 40 | 41 | //then you can declare any variables you want. 42 | unsigned long current_time; 43 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 44 | float freq1; 45 | float freq2; 46 | float freq3; 47 | float freq4; 48 | float amp1, amp2, amp3, amp4; 49 | 50 | void setup() { 51 | start_bleep_base(); //run this first in setup 52 | 53 | //there's a lot we need to do in setup now but most of it is just copy paste. 54 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 55 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 56 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 57 | // It's usually the delay and reverb that hog it. 58 | AudioMemory(500); 59 | 60 | sgtl5000_1.enable(); //Turn the adapter board on 61 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 62 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 63 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 64 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 65 | 66 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 67 | // For headphones it's pretty loud at .4 68 | // There are lots of places we can change the final volume level. 69 | // For now lets set this one once and leave it alone. 70 | sgtl5000_1.volume(0.25); 71 | 72 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 73 | // If you're not using the line out don't worry about it. 74 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 75 | 76 | 77 | //This next group can be done anywhere in the code but we want to start things with these 78 | // values and change some of them in the loop. 79 | 80 | //Notice we start by writing the object we want, then a period, then the function 81 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 82 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 83 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 84 | waveform2.begin(1, 440.0, WAVEFORM_SQUARE); 85 | waveform3.begin(1, 220.0, WAVEFORM_SAWTOOTH); 86 | waveform4.begin(1, 440.0, WAVEFORM_SQUARE); 87 | 88 | //The mixer has four inputs we can change the volume of 89 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 90 | // A gain of 1 means the output is the same as the input. 91 | // .5 would be half volume and 2 would be double 92 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 93 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 94 | mixer1.gain(0, .25); 95 | mixer1.gain(1, .25); 96 | mixer1.gain(2, .25); 97 | mixer1.gain(3, .25); 98 | 99 | mixer2.gain(0, .5); 100 | mixer2.gain(1, .5); 101 | 102 | mixer3.gain(0, .5); 103 | mixer3.gain(1, .5); 104 | 105 | delay1.delay(0, 1000); 106 | 107 | } //setup is over 108 | 109 | 110 | void loop() { 111 | update_controls(); 112 | current_time = millis(); 113 | 114 | freq1 = (1.0 - potRead(0)) * 1000.0; 115 | //freq1=potRead(0)*1000.0; 116 | waveform1.frequency(freq1); 117 | 118 | freq2 = freq1 * (potRead(1) + 1.0); 119 | waveform2.frequency(freq2); 120 | 121 | freq3 = freq1 * (potRead(2) + 1.0); 122 | waveform3.frequency(freq3); 123 | 124 | freq4 = freq1 * (potRead(3) + 1.0); 125 | waveform4.frequency(freq4); 126 | 127 | amp1 = 1.0 - potRead(4); 128 | mixer2.gain(1, amp1); 129 | 130 | amp2 = potRead(5); 131 | amp3 = 1.0 - amp2; 132 | 133 | mixer3.gain(0, amp2); 134 | mixer3.gain(1, amp3); 135 | 136 | 137 | /* 138 | amp1 = potRead(4) * .25; 139 | mixer1.gain(0, amp1); 140 | 141 | amp2 = potRead(5) * .25; 142 | mixer1.gain(1, amp2); 143 | 144 | amp3 = potRead(6) * .25; 145 | mixer1.gain(2, amp3); 146 | 147 | amp4 = potRead(7) * .25; 148 | mixer1.gain(3, amp4); 149 | */ 150 | 151 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 152 | if (current_time - prev_time[0] > 100) { 153 | prev_time[0] = current_time; 154 | Serial.println(amp2); 155 | Serial.println(amp3); 156 | 157 | //Here we print out the usage of the audio library 158 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 159 | // If you're using too many block, jut increas the number up top untill you're over it by a few 160 | Serial.print("processor: "); 161 | Serial.print(AudioProcessorUsageMax()); 162 | Serial.print("% Memory: "); 163 | Serial.print(AudioMemoryUsageMax()); 164 | Serial.println(); 165 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 166 | AudioMemoryUsageMaxReset(); 167 | } 168 | 169 | }// loop is over 170 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code_w_delay_2/Audio_basic_code_w_delay_2.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // GUItool: begin automatically generated code 15 | AudioSynthWaveform waveform3; //xy=113.00566482543945,186.00564193725586 16 | AudioSynthWaveform waveform4; //xy=130.0056610107422,244.0056610107422 17 | AudioSynthWaveform waveform2; //xy=130.9999713897705,137.99996280670166 18 | AudioSynthWaveform waveform1; //xy=153.99996948242188,91.99997901916504 19 | AudioMixer4 mixer1; //xy=313.9999237060547,165.9999542236328 20 | AudioEffectDelay delay1; //xy=474.75568771362305,391.50562286376953 21 | AudioMixer4 mixer2; //xy=484.5054988861084,262.2555961608887 22 | AudioMixer4 mixer3; //xy=563.2556304931641,153.75567626953125 23 | AudioEffectDelay delay2; //xy=710.0071182250977,238.75708961486816 24 | AudioOutputI2S i2s1; //xy=788.7498474121094,90.99997282028198 25 | AudioConnection patchCord1(waveform3, 0, mixer1, 2); 26 | AudioConnection patchCord2(waveform4, 0, mixer1, 3); 27 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 28 | AudioConnection patchCord4(waveform1, 0, mixer1, 0); 29 | AudioConnection patchCord5(mixer1, 0, mixer2, 0); 30 | AudioConnection patchCord6(mixer1, 0, mixer3, 0); 31 | AudioConnection patchCord7(delay1, 0, mixer2, 1); 32 | AudioConnection patchCord8(mixer2, delay1); 33 | AudioConnection patchCord9(mixer2, 0, mixer3, 1); 34 | AudioConnection patchCord10(mixer3, 0, i2s1, 0); 35 | AudioConnection patchCord11(mixer3, delay2); 36 | AudioConnection patchCord12(delay2, 0, i2s1, 1); 37 | AudioControlSGTL5000 sgtl5000_1; //xy=181.9999237060547,546.9999809265137 38 | // GUItool: end automatically generated code 39 | 40 | 41 | 42 | #include "bleep_base.h" //Then we can add this line that we will still need 43 | 44 | //then you can declare any variables you want. 45 | unsigned long current_time; 46 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 47 | float freq1; 48 | float freq2; 49 | float freq3; 50 | float freq4; 51 | float amp1, amp2, amp3, amp4; 52 | float dtime; 53 | 54 | void setup() { 55 | start_bleep_base(); //run this first in setup 56 | 57 | //there's a lot we need to do in setup now but most of it is just copy paste. 58 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 59 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 60 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 61 | // It's usually the delay and reverb that hog it. 62 | AudioMemory(1000); 63 | 64 | sgtl5000_1.enable(); //Turn the adapter board on 65 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 66 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 67 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 68 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 69 | 70 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 71 | // For headphones it's pretty loud at .4 72 | // There are lots of places we can change the final volume level. 73 | // For now lets set this one once and leave it alone. 74 | sgtl5000_1.volume(0.25); 75 | 76 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 77 | // If you're not using the line out don't worry about it. 78 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 79 | 80 | 81 | //This next group can be done anywhere in the code but we want to start things with these 82 | // values and change some of them in the loop. 83 | 84 | //Notice we start by writing the object we want, then a period, then the function 85 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 86 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 87 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 88 | waveform2.begin(1, 440.0, WAVEFORM_SQUARE); 89 | waveform3.begin(1, 220.0, WAVEFORM_SAWTOOTH); 90 | waveform4.begin(1, 440.0, WAVEFORM_SQUARE); 91 | 92 | //The mixer has four inputs we can change the volume of 93 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 94 | // A gain of 1 means the output is the same as the input. 95 | // .5 would be half volume and 2 would be double 96 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 97 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 98 | mixer1.gain(0, .25); 99 | mixer1.gain(1, .25); 100 | mixer1.gain(2, .25); 101 | mixer1.gain(3, .25); 102 | 103 | mixer2.gain(0, .5); 104 | mixer2.gain(1, .5); 105 | 106 | mixer3.gain(0, .5); 107 | mixer3.gain(1, .5); 108 | 109 | delay1.delay(0, 1000); 110 | delay2.delay(0, 50); 111 | 112 | } //setup is over 113 | 114 | 115 | void loop() { 116 | update_controls(); 117 | current_time = millis(); 118 | 119 | freq1 = (1.0 - potRead(0)) * 1000.0; 120 | //freq1=potRead(0)*1000.0; 121 | waveform1.frequency(freq1); 122 | 123 | freq2 = freq1 * (potRead(1) + 1.0); 124 | waveform2.frequency(freq2); 125 | 126 | freq3 = freq1 * (potRead(2) + 1.0); 127 | waveform3.frequency(freq3); 128 | 129 | freq4 = freq1 * (potRead(3) + 1.0); 130 | waveform4.frequency(freq4); 131 | 132 | amp1 = 1.0 - potRead(4); 133 | mixer2.gain(1, amp1); 134 | 135 | amp2 = potRead(5); 136 | amp3 = 1.0 - amp2; 137 | 138 | mixer3.gain(0, amp2); 139 | mixer3.gain(1, amp3); 140 | 141 | dtime = potRead(6) * 1000.0; 142 | // delay1.delay(0, dtime); //sounds glitchy 143 | 144 | 145 | /* 146 | amp1 = potRead(4) * .25; 147 | mixer1.gain(0, amp1); 148 | 149 | amp2 = potRead(5) * .25; 150 | mixer1.gain(1, amp2); 151 | 152 | amp3 = potRead(6) * .25; 153 | mixer1.gain(2, amp3); 154 | 155 | amp4 = potRead(7) * .25; 156 | mixer1.gain(3, amp4); 157 | */ 158 | 159 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 160 | if (current_time - prev_time[0] > 100) { 161 | prev_time[0] = current_time; 162 | Serial.println(amp2); 163 | Serial.println(amp3); 164 | 165 | //Here we print out the usage of the audio library 166 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 167 | // If you're using too many block, jut increas the number up top untill you're over it by a few 168 | Serial.print("processor: "); 169 | Serial.print(AudioProcessorUsageMax()); 170 | Serial.print("% Memory: "); 171 | Serial.print(AudioMemoryUsageMax()); 172 | Serial.println(); 173 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 174 | AudioMemoryUsageMaxReset(); 175 | } 176 | 177 | }// loop is over 178 | -------------------------------------------------------------------------------- /Class-3/Audio_basic_code_w_delay_and_AM/Audio_basic_code_w_delay_and_AM.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // GUItool: begin automatically generated code 15 | AudioSynthWaveform waveform3; //xy=113.00566482543945,186.00564193725586 16 | AudioSynthWaveform waveform4; //xy=130.0056610107422,244.0056610107422 17 | AudioSynthWaveform waveform2; //xy=130.9999713897705,137.99996280670166 18 | AudioSynthWaveform waveform5; //xy=133.75,333.75 19 | AudioSynthWaveform waveform1; //xy=153.99996948242188,91.99997901916504 20 | AudioMixer4 mixer1; //xy=286.49996185302734,170.99995613098145 21 | AudioEffectMultiply multiply1; //xy=438.750036239624,203.7500171661377 22 | AudioEffectDelay delay1; //xy=459.75562286376953,444.0056266784668 23 | AudioMixer4 mixer2; //xy=470.7553825378418,313.50562286376953 24 | AudioMixer4 mixer3; //xy=637.0056304931641,153.75568008422852 25 | AudioOutputI2S i2s1; //xy=788.7498474121094,90.99997282028198 26 | AudioConnection patchCord1(waveform3, 0, mixer1, 2); 27 | AudioConnection patchCord2(waveform4, 0, mixer1, 3); 28 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 29 | AudioConnection patchCord4(waveform5, 0, multiply1, 1); 30 | AudioConnection patchCord5(waveform1, 0, mixer1, 0); 31 | AudioConnection patchCord6(mixer1, 0, multiply1, 0); 32 | AudioConnection patchCord7(multiply1, 0, mixer3, 0); 33 | AudioConnection patchCord8(multiply1, 0, mixer2, 0); 34 | AudioConnection patchCord9(delay1, 0, mixer2, 1); 35 | AudioConnection patchCord10(delay1, 1, mixer2, 2); 36 | AudioConnection patchCord11(delay1, 2, mixer2, 3); 37 | AudioConnection patchCord12(mixer2, delay1); 38 | AudioConnection patchCord13(mixer2, 0, mixer3, 1); 39 | AudioConnection patchCord14(mixer3, 0, i2s1, 0); 40 | AudioConnection patchCord15(mixer3, 0, i2s1, 1); 41 | AudioControlSGTL5000 sgtl5000_1; //xy=244.49993133544922,642.0000157356262 42 | // GUItool: end automatically generated code 43 | 44 | 45 | 46 | 47 | #include "bleep_base.h" //Then we can add this line that we will still need 48 | 49 | //then you can declare any variables you want. 50 | unsigned long current_time; 51 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 52 | float freq1; 53 | float freq2; 54 | float freq3; 55 | float freq4; 56 | float freq5; 57 | float amp1, amp2, amp3, amp4; 58 | float dtime; 59 | 60 | void setup() { 61 | start_bleep_base(); //run this first in setup 62 | 63 | //there's a lot we need to do in setup now but most of it is just copy paste. 64 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 65 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 66 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 67 | // It's usually the delay and reverb that hog it. 68 | AudioMemory(1000); 69 | 70 | sgtl5000_1.enable(); //Turn the adapter board on 71 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 72 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 73 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 74 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 75 | 76 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 77 | // For headphones it's pretty loud at .4 78 | // There are lots of places we can change the final volume level. 79 | // For now lets set this one once and leave it alone. 80 | sgtl5000_1.volume(0.25); 81 | 82 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 83 | // If you're not using the line out don't worry about it. 84 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 85 | 86 | 87 | //This next group can be done anywhere in the code but we want to start things with these 88 | // values and change some of them in the loop. 89 | 90 | //Notice we start by writing the object we want, then a period, then the function 91 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 92 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 93 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 94 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 95 | waveform3.begin(1, 220.0, WAVEFORM_SINE); 96 | waveform4.begin(1, 440.0, WAVEFORM_SINE); 97 | waveform5.begin(1, 440.0, WAVEFORM_SINE); 98 | 99 | //The mixer has four inputs we can change the volume of 100 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 101 | // A gain of 1 means the output is the same as the input. 102 | // .5 would be half volume and 2 would be double 103 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 104 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 105 | mixer1.gain(0, .25); 106 | mixer1.gain(1, .25); 107 | mixer1.gain(2, .25); 108 | mixer1.gain(3, .25); 109 | 110 | mixer2.gain(0, .5); 111 | mixer2.gain(1, .5); 112 | 113 | mixer3.gain(0, .5); 114 | mixer3.gain(1, .5); 115 | 116 | delay1.delay(0, 1000); 117 | delay1.delay(0, 900); 118 | delay1.delay(0, 800); 119 | //delay2.delay(0, 50); 120 | 121 | } //setup is over 122 | 123 | 124 | void loop() { 125 | update_controls(); 126 | current_time = millis(); 127 | 128 | freq1 = (1.0 - potRead(0)) * 1000.0; 129 | //freq1=potRead(0)*1000.0; 130 | waveform1.frequency(freq1); 131 | 132 | freq2 = freq1 * (potRead(1) + 1.0); 133 | waveform2.frequency(freq2); 134 | 135 | freq3 = freq1 * (potRead(2) + 1.0); 136 | waveform3.frequency(freq3); 137 | 138 | freq4 = freq1 * (potRead(3) + 1.0); 139 | waveform4.frequency(freq4); 140 | 141 | freq5 = potRead(7)*400.0; 142 | waveform5.frequency(freq5); 143 | 144 | 145 | amp1 = 1.0 - potRead(4); 146 | mixer2.gain(1, amp1); 147 | mixer2.gain(2, amp1); 148 | mixer2.gain(3, amp1); 149 | 150 | amp2 = potRead(5); 151 | amp3 = 1.0 - amp2; 152 | 153 | mixer3.gain(0, amp2); 154 | mixer3.gain(1, amp3); 155 | 156 | dtime = potRead(6) * 1000.0; 157 | // delay1.delay(0, dtime); //sounds glitchy 158 | 159 | 160 | /* 161 | amp1 = potRead(4) * .25; 162 | mixer1.gain(0, amp1); 163 | 164 | amp2 = potRead(5) * .25; 165 | mixer1.gain(1, amp2); 166 | 167 | amp3 = potRead(6) * .25; 168 | mixer1.gain(2, amp3); 169 | 170 | amp4 = potRead(7) * .25; 171 | mixer1.gain(3, amp4); 172 | */ 173 | 174 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 175 | if (current_time - prev_time[0] > 100) { 176 | prev_time[0] = current_time; 177 | Serial.println(amp2); 178 | Serial.println(amp3); 179 | 180 | //Here we print out the usage of the audio library 181 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 182 | // If you're using too many block, jut increas the number up top untill you're over it by a few 183 | Serial.print("processor: "); 184 | Serial.print(AudioProcessorUsageMax()); 185 | Serial.print("% Memory: "); 186 | Serial.print(AudioMemoryUsageMax()); 187 | Serial.println(); 188 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 189 | AudioMemoryUsageMaxReset(); 190 | } 191 | 192 | }// loop is over 193 | -------------------------------------------------------------------------------- /Class-4/Class_4_-_Envelope_1/Class_4_-_Envelope_1.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=272,247 17 | AudioSynthWaveform waveform3; //xy=272,369 18 | AudioSynthWaveform waveform1; //xy=274,205 19 | AudioAnalyzePeak peak1; //xy=414,352 20 | AudioMixer4 mixer1; //xy=451,249 21 | AudioFilterStateVariable filter1; //xy=607,239 22 | AudioEffectEnvelope envelope1; //xy=796,257 23 | AudioOutputI2S i2s1; //xy=852,330 24 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 25 | AudioConnection patchCord2(waveform3, peak1); 26 | AudioConnection patchCord3(waveform1, 0, mixer1, 0); 27 | AudioConnection patchCord4(mixer1, 0, filter1, 0); 28 | AudioConnection patchCord5(filter1, 0, envelope1, 0); 29 | AudioConnection patchCord6(envelope1, 0, i2s1, 0); 30 | AudioConnection patchCord7(envelope1, 0, i2s1, 1); 31 | AudioControlSGTL5000 sgtl5000_1; //xy=614.4999389648438,388 32 | // GUItool: end automatically generated code 33 | 34 | #include "bleep_base.h" //Then we can add this line that we will still need 35 | 36 | //then you can declare any variables you want. 37 | unsigned long current_time; 38 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 39 | int current_button_reading; 40 | int prev_reading; 41 | 42 | void setup() { 43 | start_bleep_base(); //run this first in setup 44 | 45 | //How much RAM to set aside for the audio library to use. 46 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 47 | // On our Teensy 3.2 we can go up to about 200 but that won't leave any RAM for anyone else. 48 | // It's usually the delay and reverb that hog it. 49 | AudioMemory(10); 50 | 51 | sgtl5000_1.enable(); //Turn the adapter board on 52 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary yet but good to have 53 | sgtl5000_1.lineInLevel(13); //The volume of the input. Again we'll get to this later 54 | 55 | //Output volume. Goes from 0.0 to 1.0 but a fully loud signal will clip over .8 or so. 56 | // For headphones it's pretty loud at .4 57 | // There are lots of places we can change the final volume level. This one you set once and leave alone. 58 | sgtl5000_1.volume(0.25); 59 | 60 | //This next group can be done anywhere in the code but we want to start things with these 61 | // values and change some of them in the loop. 62 | 63 | //Notice we start by writing the object we want, then a period, then the function 64 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 65 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 66 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 67 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 68 | waveform3.begin(1, 440.0, WAVEFORM_SINE); 69 | 70 | filter1.frequency(12000); 71 | filter1.resonance(.7); 72 | 73 | //The mixer has four inputs we can change the volume of 74 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 75 | // A gain of 1 means the output is the same as the input. 76 | // .5 would be half volume and 2 would be double 77 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 78 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 79 | mixer1.gain(0, .4); 80 | mixer1.gain(1, .4); 81 | mixer1.gain(2, 0); 82 | mixer1.gain(3, 0); 83 | 84 | } 85 | 86 | void loop() { 87 | update_controls(); 88 | current_time = millis(); 89 | 90 | prev_reading = current_button_reading; 91 | current_button_reading=buttonRead(0); 92 | 93 | if (prev_reading==1 && current_button_reading==0){ 94 | envelope1.noteOn(); 95 | } 96 | if (prev_reading==0 && current_button_reading==1){ 97 | envelope1.noteOff(); 98 | } 99 | 100 | 101 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 102 | if (current_time - prev_time[0] > 500) { 103 | prev_time[0] = current_time; 104 | 105 | //Here we print out the usage of the audio library 106 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 107 | // If you're using too many block, jut increas the number up top untill you're over it by a few 108 | Serial.print("processor: "); 109 | Serial.print(AudioProcessorUsageMax()); 110 | Serial.print("% Memory: "); 111 | Serial.print(AudioMemoryUsageMax()); 112 | Serial.println(); 113 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 114 | AudioMemoryUsageMaxReset(); 115 | } 116 | 117 | }// loop is over 118 | -------------------------------------------------------------------------------- /Class-4/Class_4_-_Envelope_2/Class_4_-_Envelope_2.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=272,247 17 | AudioSynthWaveform waveform3; //xy=272,369 18 | AudioSynthWaveform waveform1; //xy=274,205 19 | AudioAnalyzePeak peak1; //xy=414,352 20 | AudioMixer4 mixer1; //xy=451,249 21 | AudioFilterStateVariable filter1; //xy=607,239 22 | AudioEffectEnvelope envelope1; //xy=796,257 23 | AudioOutputI2S i2s1; //xy=852,330 24 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 25 | AudioConnection patchCord2(waveform3, peak1); 26 | AudioConnection patchCord3(waveform1, 0, mixer1, 0); 27 | AudioConnection patchCord4(mixer1, 0, filter1, 0); 28 | AudioConnection patchCord5(filter1, 0, envelope1, 0); 29 | AudioConnection patchCord6(envelope1, 0, i2s1, 0); 30 | AudioConnection patchCord7(envelope1, 0, i2s1, 1); 31 | AudioControlSGTL5000 sgtl5000_1; //xy=614.4999389648438,388 32 | // GUItool: end automatically generated code 33 | 34 | #include "bleep_base.h" //Then we can add this line that we will still need 35 | 36 | //then you can declare any variables you want. 37 | unsigned long current_time; 38 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 39 | int current_button_reading[6]; 40 | int prev_reading[6]; 41 | float attack_adj, sustain_adj, release_adj; 42 | 43 | void setup() { 44 | start_bleep_base(); //run this first in setup 45 | 46 | //How much RAM to set aside for the audio library to use. 47 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 48 | // On our Teensy 3.2 we can go up to about 200 but that won't leave any RAM for anyone else. 49 | // It's usually the delay and reverb that hog it. 50 | AudioMemory(10); 51 | 52 | sgtl5000_1.enable(); //Turn the adapter board on 53 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary yet but good to have 54 | sgtl5000_1.lineInLevel(13); //The volume of the input. Again we'll get to this later 55 | 56 | //Output volume. Goes from 0.0 to 1.0 but a fully loud signal will clip over .8 or so. 57 | // For headphones it's pretty loud at .4 58 | // There are lots of places we can change the final volume level. This one you set once and leave alone. 59 | sgtl5000_1.volume(0.25); 60 | 61 | //This next group can be done anywhere in the code but we want to start things with these 62 | // values and change some of them in the loop. 63 | 64 | //Notice we start by writing the object we want, then a period, then the function 65 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 66 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 67 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 68 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 69 | waveform3.begin(1, 440.0, WAVEFORM_SINE); 70 | 71 | filter1.frequency(12000); 72 | filter1.resonance(.7); 73 | 74 | envelope1.sustain(1.0); 75 | 76 | //The mixer has four inputs we can change the volume of 77 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 78 | // A gain of 1 means the output is the same as the input. 79 | // .5 would be half volume and 2 would be double 80 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 81 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 82 | mixer1.gain(0, .4); 83 | mixer1.gain(1, .4); 84 | mixer1.gain(2, 0); 85 | mixer1.gain(3, 0); 86 | 87 | } 88 | 89 | void loop() { 90 | update_controls(); 91 | current_time = millis(); 92 | 93 | prev_reading[0] = current_button_reading[0]; 94 | current_button_reading[0] = buttonRead(0); 95 | 96 | if (prev_reading[0] == 1 && current_button_reading[0] == 0) { 97 | envelope1.noteOn(); 98 | waveform1.frequency(220.0); 99 | waveform2.frequency(220.0 * 2.0); 100 | } 101 | 102 | if (prev_reading[0] == 0 && current_button_reading[0] == 1) { 103 | envelope1.noteOff(); 104 | } 105 | 106 | prev_reading[1] = current_button_reading[1]; 107 | current_button_reading[1] = buttonRead(1); 108 | 109 | if (prev_reading[1] == 1 && current_button_reading[1] == 0) { 110 | envelope1.noteOn(); 111 | waveform1.frequency(233.0819); 112 | waveform2.frequency(233.0819 * 2.0); 113 | } 114 | if (prev_reading[1] == 0 && current_button_reading[1] == 1) { 115 | envelope1.noteOff(); 116 | } 117 | 118 | attack_adj = (1.0 - potRead(0)) * 1000.0; 119 | envelope1.attack(attack_adj); 120 | 121 | release_adj = (1.0 - potRead(1)) * 2500.0; 122 | envelope1.release(release_adj); 123 | 124 | 125 | 126 | 127 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 128 | if (current_time - prev_time[0] > 50) { 129 | prev_time[0] = current_time; 130 | Serial.println(attack_adj); 131 | Serial.println(release_adj); 132 | Serial.println(); 133 | 134 | //Here we print out the usage of the audio library 135 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 136 | // If you're using too many block, jut increas the number up top untill you're over it by a few 137 | Serial.print("processor: "); 138 | Serial.print(AudioProcessorUsageMax()); 139 | Serial.print("% Memory: "); 140 | Serial.print(AudioMemoryUsageMax()); 141 | Serial.println(); 142 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 143 | AudioMemoryUsageMaxReset(); 144 | } 145 | 146 | }// loop is over 147 | -------------------------------------------------------------------------------- /Class-4/Class_4_-_Envelope_3_w_all_keys/Class_4_-_Envelope_3_w_all_keys.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=272,247 17 | AudioSynthWaveform waveform3; //xy=272,369 18 | AudioSynthWaveform waveform1; //xy=274,205 19 | AudioAnalyzePeak peak1; //xy=414,352 20 | AudioMixer4 mixer1; //xy=451,249 21 | AudioFilterStateVariable filter1; //xy=607,239 22 | AudioEffectEnvelope envelope1; //xy=796,257 23 | AudioOutputI2S i2s1; //xy=852,330 24 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 25 | AudioConnection patchCord2(waveform3, peak1); 26 | AudioConnection patchCord3(waveform1, 0, mixer1, 0); 27 | AudioConnection patchCord4(mixer1, 0, filter1, 0); 28 | AudioConnection patchCord5(filter1, 0, envelope1, 0); 29 | AudioConnection patchCord6(envelope1, 0, i2s1, 0); 30 | AudioConnection patchCord7(envelope1, 0, i2s1, 1); 31 | AudioControlSGTL5000 sgtl5000_1; //xy=614.4999389648438,388 32 | // GUItool: end automatically generated code 33 | 34 | #include "bleep_base.h" //Then we can add this line that we will still need 35 | 36 | //then you can declare any variables you want. 37 | unsigned long current_time; 38 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 39 | int current_button_reading[6]; 40 | int prev_reading[6]; 41 | float attack_adj, sustain_adj, release_adj; 42 | float freq1; 43 | float note_offset; 44 | float fiter_freq; 45 | float lfo_reading; 46 | float lfo_freq; 47 | 48 | void setup() { 49 | start_bleep_base(); //run this first in setup 50 | 51 | //How much RAM to set aside for the audio library to use. 52 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 53 | // On our Teensy 3.2 we can go up to about 200 but that won't leave any RAM for anyone else. 54 | // It's usually the delay and reverb that hog it. 55 | AudioMemory(10); 56 | 57 | sgtl5000_1.enable(); //Turn the adapter board on 58 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary yet but good to have 59 | sgtl5000_1.lineInLevel(13); //The volume of the input. Again we'll get to this later 60 | 61 | //Output volume. Goes from 0.0 to 1.0 but a fully loud signal will clip over .8 or so. 62 | // For headphones it's pretty loud at .4 63 | // There are lots of places we can change the final volume level. This one you set once and leave alone. 64 | sgtl5000_1.volume(0.25); 65 | 66 | //This next group can be done anywhere in the code but we want to start things with these 67 | // values and change some of them in the loop. 68 | 69 | //Notice we start by writing the object we want, then a period, then the function 70 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 71 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 72 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 73 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 74 | waveform3.begin(1, 0.5, WAVEFORM_SINE); 75 | 76 | filter1.frequency(12000); 77 | filter1.resonance(.7); 78 | 79 | envelope1.sustain(1.0); 80 | 81 | //The mixer has four inputs we can change the volume of 82 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 83 | // A gain of 1 means the output is the same as the input. 84 | // .5 would be half volume and 2 would be double 85 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 86 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 87 | mixer1.gain(0, .4); 88 | mixer1.gain(1, .4); 89 | mixer1.gain(2, 0); 90 | mixer1.gain(3, 0); 91 | 92 | } 93 | 94 | void loop() { 95 | update_controls(); 96 | current_time = millis(); 97 | 98 | 99 | freq1 = potRead(4) * 500.0; 100 | waveform1.frequency((freq1)*note_offset); 101 | waveform2.frequency((freq1 * 2.001)*note_offset); 102 | 103 | for (int j = 0; j < 6; j++) { 104 | prev_reading[j] = current_button_reading[j]; 105 | current_button_reading[j] = buttonRead(j); 106 | 107 | if (prev_reading[j] == 1 && current_button_reading[j] == 0) { 108 | envelope1.noteOn(); 109 | note_offset = (j + 1.0); 110 | } 111 | 112 | if (prev_reading[j] == 0 && current_button_reading[j] == 1) { 113 | envelope1.noteOff(); 114 | } 115 | } 116 | 117 | //fiter_freq = (potRead(5) * 10000.0)+(lfo_reading*200.0); //not great at high frequencies 118 | fiter_freq = (potRead(5) * 10000.0) * (1.0 + (lfo_reading * 2.5)); 119 | if (fiter_freq > 15000) { 120 | fiter_freq = 15000; 121 | } 122 | filter1.frequency(fiter_freq); //if we go over 18000 it freaks out 123 | 124 | if (peak1.available()) { 125 | lfo_reading = peak1.read(); 126 | } 127 | lfo_freq=potRead(6) * 10.0; 128 | waveform3.frequency(lfo_freq); 129 | 130 | 131 | attack_adj = (1.0 - potRead(0)) * 1000.0; 132 | envelope1.attack(attack_adj); 133 | 134 | release_adj = (1.0 - potRead(1)) * 2500.0; 135 | envelope1.release(release_adj); 136 | 137 | 138 | 139 | 140 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 141 | if (current_time - prev_time[0] > 50) { 142 | prev_time[0] = current_time; 143 | //Serial.println(attack_adj); 144 | // Serial.println(release_adj); 145 | Serial.println(lfo_reading); 146 | 147 | if (0) {//cahge this to 1 and it'll print 148 | Serial.print("processor: "); 149 | Serial.print(AudioProcessorUsageMax()); 150 | Serial.print("% Memory: "); 151 | Serial.print(AudioMemoryUsageMax()); 152 | Serial.println(); 153 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 154 | AudioMemoryUsageMaxReset(); 155 | } 156 | } 157 | 158 | }// loop is over 159 | -------------------------------------------------------------------------------- /Class-4/Class_4_-_Envelope_4_w_delay/Class_4_-_Envelope_4_w_delay.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform1; //xy=262,197 17 | AudioSynthWaveform waveform3; //xy=274,516 18 | AudioSynthWaveformDc dc1; //xy=276,366 19 | AudioSynthWaveform waveform2; //xy=278,240 20 | AudioAnalyzePeak peak1; //xy=422,554 21 | AudioMixer4 mixer1; //xy=439,220 22 | AudioEffectEnvelope envelope2; //xy=444,369 23 | AudioFilterStateVariable filter1; //xy=613,273 24 | AudioEffectEnvelope envelope1; //xy=639,197 25 | AudioEffectDelay delay1; //xy=841,414 26 | AudioMixer4 mixer2; //xy=845,268 27 | AudioOutputI2S i2s1; //xy=1019,215 28 | AudioConnection patchCord1(waveform1, 0, mixer1, 0); 29 | AudioConnection patchCord2(waveform3, peak1); 30 | AudioConnection patchCord3(dc1, envelope2); 31 | AudioConnection patchCord4(waveform2, 0, mixer1, 1); 32 | AudioConnection patchCord5(mixer1, 0, filter1, 0); 33 | AudioConnection patchCord6(envelope2, 0, filter1, 1); 34 | AudioConnection patchCord7(filter1, 0, envelope1, 0); 35 | AudioConnection patchCord8(envelope1, 0, mixer2, 0); 36 | AudioConnection patchCord9(delay1, 0, mixer2, 1); 37 | AudioConnection patchCord10(mixer2, 0, i2s1, 0); 38 | AudioConnection patchCord11(mixer2, 0, i2s1, 1); 39 | AudioConnection patchCord12(mixer2, delay1); 40 | AudioControlSGTL5000 sgtl5000_1; //xy=167.49993896484375,131 41 | // GUItool: end automatically generated code 42 | 43 | 44 | #include "bleep_base.h" //Then we can add this line that we will still need 45 | 46 | //then you can declare any variables you want. 47 | unsigned long current_time, last_time; 48 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 49 | int current_button_reading[6]; 50 | int prev_reading[6]; 51 | float attack_adj, sustain_adj, release_adj; 52 | float freq1; 53 | float note_offset; 54 | float fiter_freq; 55 | float lfo_reading; 56 | float lfo_freq; 57 | 58 | 59 | void setup() { 60 | start_bleep_base(); //run this first in setup 61 | 62 | 63 | AudioMemory(200); 64 | 65 | sgtl5000_1.enable(); //Turn the adapter board on 66 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary yet but good to have 67 | sgtl5000_1.lineInLevel(13); //The volume of the input. Again we'll get to this later 68 | 69 | //Output volume. Goes from 0.0 to 1.0 but a fully loud signal will clip over .8 or so. 70 | // For headphones it's pretty loud at .4 71 | // There are lots of places we can change the final volume level. This one you set once and leave alone. 72 | sgtl5000_1.volume(0.25); 73 | 74 | //This next group can be done anywhere in the code but we want to start things with these 75 | // values and change some of them in the loop. 76 | 77 | //Notice we start by writing the object we want, then a period, then the function 78 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 79 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 80 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 81 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 82 | waveform3.begin(1, 0.5, WAVEFORM_SINE); 83 | 84 | filter1.frequency(12000); 85 | filter1.resonance(4.5); 86 | 87 | envelope1.sustain(1.0); 88 | dc1.amplitude(1.0); 89 | 90 | envelope2.attack(200); 91 | envelope2.decay(200); 92 | envelope2.sustain(0.4); 93 | envelope2.release(500); 94 | 95 | 96 | 97 | 98 | //The mixer has four inputs we can change the volume of 99 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 100 | // A gain of 1 means the output is the same as the input. 101 | // .5 would be half volume and 2 would be double 102 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 103 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 104 | mixer1.gain(0, .3); 105 | mixer1.gain(1, .3); 106 | mixer1.gain(2, 0); 107 | mixer1.gain(3, 0); 108 | 109 | 110 | delay1.delay(0, 500); 111 | 112 | } 113 | 114 | void loop() { 115 | update_controls(); 116 | last_time = current_time; 117 | current_time = millis(); 118 | 119 | 120 | 121 | freq1 = potRead(4) * 500.0; 122 | waveform1.frequency((freq1)*note_offset); 123 | waveform2.frequency((freq1 * 2.001)*note_offset); 124 | 125 | for (int j = 0; j < 6; j++) { 126 | prev_reading[j] = current_button_reading[j]; 127 | current_button_reading[j] = buttonRead(j); 128 | 129 | if (prev_reading[j] == 1 && current_button_reading[j] == 0) { 130 | envelope1.noteOn(); 131 | envelope2.noteOn(); 132 | note_offset = (j + 1.0); 133 | } 134 | 135 | if (prev_reading[j] == 0 && current_button_reading[j] == 1) { 136 | envelope1.noteOff(); 137 | envelope2.noteOff(); 138 | } 139 | } 140 | 141 | fiter_freq = (potRead(5) * 10000.0) + (lfo_reading * 200.0); //not great at high frequencies 142 | //fiter_freq = (potRead(5) * 10000.0) * (1.0 + (lfo_reading * 2.5)); 143 | //fiter_freq = (potRead(5) * 10000.0); 144 | if (fiter_freq > 15000) { 145 | fiter_freq = 15000; 146 | } 147 | filter1.frequency(fiter_freq); //if we go over 18000 it freaks out 148 | 149 | if (peak1.available()) { 150 | lfo_reading = peak1.read(); 151 | } 152 | 153 | lfo_freq = potRead(6) * 10.0; 154 | waveform3.frequency(lfo_freq); 155 | 156 | attack_adj = (1.0 - potRead(0)) * 1000.0; 157 | envelope1.attack(attack_adj); 158 | 159 | release_adj = (1.0 - potRead(1)) * 2500.0; 160 | envelope1.release(release_adj); 161 | 162 | mixer2.gain(0, potRead(3) * 2.0); 163 | mixer2.gain(1, potRead(7) * 2.0); 164 | 165 | 166 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 167 | if (current_time - prev_time[0] > 50) { 168 | prev_time[0] = current_time; 169 | //Serial.println(attack_adj); 170 | // Serial.println(release_adj); 171 | Serial.println(current_time - last_time); 172 | 173 | 174 | if (1) {//cahge this to 1 and it'll print 175 | Serial.print("processor: "); 176 | Serial.print(AudioProcessorUsageMax()); 177 | Serial.print("% Memory: "); 178 | Serial.print(AudioMemoryUsageMax()); 179 | Serial.println(); 180 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 181 | AudioMemoryUsageMaxReset(); 182 | } 183 | } 184 | 185 | }// loop is over 186 | -------------------------------------------------------------------------------- /Class-4/Class_4_-_Envelope_5_w_crush/Class_4_-_Envelope_5_w_crush.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // GUItool: begin automatically generated code 15 | AudioSynthWaveform waveform1; //xy=262,197 16 | AudioSynthWaveform waveform3; //xy=274,516 17 | AudioSynthWaveformDc dc1; //xy=276,366 18 | AudioSynthWaveform waveform2; //xy=278,240 19 | AudioAnalyzePeak peak1; //xy=422,554 20 | AudioMixer4 mixer1; //xy=439,220 21 | AudioEffectEnvelope envelope2; //xy=444,369 22 | AudioEffectBitcrusher bitcrusher1; //xy=460,75 23 | AudioFilterStateVariable filter1; //xy=604,291 24 | AudioEffectEnvelope envelope1; //xy=657,115 25 | AudioEffectDelay delay1; //xy=829,381 26 | AudioEffectBitcrusher bitcrusher2; //xy=832,177 27 | AudioMixer4 mixer2; //xy=834,259 28 | AudioMixer4 mixer3; //xy=979,119 29 | AudioOutputI2S i2s1; //xy=1026,257 30 | AudioConnection patchCord1(waveform1, 0, mixer1, 0); 31 | AudioConnection patchCord2(waveform3, peak1); 32 | AudioConnection patchCord3(dc1, envelope2); 33 | AudioConnection patchCord4(waveform2, 0, mixer1, 1); 34 | AudioConnection patchCord5(mixer1, 0, filter1, 0); 35 | AudioConnection patchCord6(envelope2, 0, filter1, 1); 36 | AudioConnection patchCord7(filter1, 0, envelope1, 0); 37 | AudioConnection patchCord8(envelope1, bitcrusher2); 38 | AudioConnection patchCord9(envelope1, 0, mixer3, 0); 39 | AudioConnection patchCord10(delay1, 0, mixer2, 1); 40 | AudioConnection patchCord11(bitcrusher2, 0, mixer3, 1); 41 | AudioConnection patchCord12(mixer2, 0, i2s1, 0); 42 | AudioConnection patchCord13(mixer2, 0, i2s1, 1); 43 | AudioConnection patchCord14(mixer2, delay1); 44 | AudioConnection patchCord15(mixer3, 0, mixer2, 0); 45 | AudioControlSGTL5000 sgtl5000_1; //xy=254.49993896484375,119 46 | // GUItool: end automatically generated code 47 | 48 | 49 | 50 | #include "bleep_base.h" //Then we can add this line that we will still need 51 | 52 | //then you can declare any variables you want. 53 | unsigned long current_time, last_time; 54 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 55 | int current_button_reading[6]; 56 | int prev_reading[6]; 57 | float attack_adj, sustain_adj, release_adj; 58 | float freq1; 59 | float note_offset; 60 | float fiter_freq; 61 | float lfo_reading; 62 | float lfo_freq; 63 | float crush_lvl; 64 | 65 | 66 | void setup() { 67 | start_bleep_base(); //run this first in setup 68 | 69 | 70 | AudioMemory(200); 71 | 72 | sgtl5000_1.enable(); //Turn the adapter board on 73 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary yet but good to have 74 | sgtl5000_1.lineInLevel(13); //The volume of the input. Again we'll get to this later 75 | 76 | //Output volume. Goes from 0.0 to 1.0 but a fully loud signal will clip over .8 or so. 77 | // For headphones it's pretty loud at .4 78 | // There are lots of places we can change the final volume level. This one you set once and leave alone. 79 | sgtl5000_1.volume(0.25); 80 | 81 | //This next group can be done anywhere in the code but we want to start things with these 82 | // values and change some of them in the loop. 83 | 84 | //Notice we start by writing the object we want, then a period, then the function 85 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 86 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 87 | waveform1.begin(1, 220.0, WAVEFORM_SAWTOOTH); 88 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 89 | waveform3.begin(1, 0.5, WAVEFORM_SINE); 90 | 91 | filter1.frequency(12000); 92 | filter1.resonance(4.5); 93 | 94 | envelope1.sustain(1.0); 95 | dc1.amplitude(1.0); 96 | 97 | envelope2.attack(200); 98 | envelope2.decay(200); 99 | envelope2.sustain(0.4); 100 | envelope2.release(500); 101 | 102 | 103 | 104 | 105 | //The mixer has four inputs we can change the volume of 106 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 107 | // A gain of 1 means the output is the same as the input. 108 | // .5 would be half volume and 2 would be double 109 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 110 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 111 | mixer1.gain(0, .3); 112 | mixer1.gain(1, .3); 113 | mixer1.gain(2, 0); 114 | mixer1.gain(3, 0); 115 | 116 | delay1.delay(0, 500); 117 | 118 | } 119 | 120 | void loop() { 121 | update_controls(); 122 | last_time = current_time; 123 | current_time = millis(); 124 | 125 | freq1 = potRead(4) * 500.0; 126 | waveform1.frequency((freq1)*note_offset); 127 | waveform2.frequency((freq1 * 2.001)*note_offset); 128 | 129 | for (int j = 0; j < 6; j++) { 130 | prev_reading[j] = current_button_reading[j]; 131 | current_button_reading[j] = buttonRead(j); 132 | 133 | if (prev_reading[j] == 1 && current_button_reading[j] == 0) { 134 | envelope1.noteOn(); 135 | envelope2.noteOn(); 136 | note_offset = (j + 1.0); 137 | } 138 | 139 | if (prev_reading[j] == 0 && current_button_reading[j] == 1) { 140 | envelope1.noteOff(); 141 | envelope2.noteOff(); 142 | } 143 | } 144 | 145 | fiter_freq = (potRead(5) * 10000.0) + (lfo_reading * 200.0); //not great at high frequencies 146 | //fiter_freq = (potRead(5) * 10000.0) * (1.0 + (lfo_reading * 2.5)); 147 | //fiter_freq = (potRead(5) * 10000.0); 148 | if (fiter_freq > 15000) { 149 | fiter_freq = 15000; 150 | } 151 | filter1.frequency(fiter_freq); //if we go over 18000 it freaks out 152 | 153 | if (peak1.available()) { 154 | lfo_reading = peak1.read(); 155 | } 156 | 157 | lfo_freq = potRead(6) * 10.0; 158 | waveform3.frequency(lfo_freq); 159 | 160 | attack_adj = (1.0 - potRead(0)) * 1000.0; 161 | envelope1.attack(attack_adj); 162 | 163 | release_adj = (1.0 - potRead(1)) * 2500.0; 164 | envelope1.release(release_adj); 165 | 166 | mixer2.gain(0, potRead(3) * 2.0); //input signal 167 | mixer2.gain(1, potRead(7) * 2.0); //feedback from delay 168 | 169 | mixer3.gain(0, 0); //dry 170 | mixer3.gain(1, 1.0); //from bitcrusher 171 | 172 | crush_lvl = (potRead(2) * 44000.0); 173 | bitcrusher2.sampleRate(crush_lvl); 174 | bitcrusher2.bits(16); //must be set 175 | 176 | 177 | 178 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 179 | if (current_time - prev_time[0] > 50) { 180 | prev_time[0] = current_time; 181 | //Serial.println(attack_adj); 182 | // Serial.println(release_adj); 183 | Serial.println(crush_lvl); 184 | 185 | 186 | if (1) {//cahge this to 1 and it'll print 187 | Serial.print("processor: "); 188 | Serial.print(AudioProcessorUsageMax()); 189 | Serial.print("% Memory: "); 190 | Serial.print(AudioMemoryUsageMax()); 191 | Serial.println(); 192 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 193 | AudioMemoryUsageMaxReset(); 194 | } 195 | } 196 | 197 | }// loop is over 198 | -------------------------------------------------------------------------------- /Class-5/class_5_-_8x_sine_waves/class_5_-_8x_sine_waves.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform6; //xy=145,362 17 | AudioSynthWaveform waveform5; //xy=151,323 18 | AudioSynthWaveform waveform4; //xy=158,290 19 | AudioSynthWaveform waveform7; //xy=162,397 20 | AudioSynthWaveform waveform2; //xy=163,213.00000381469727 21 | AudioSynthWaveform waveform3; //xy=163,258 22 | AudioSynthWaveform waveform1; //xy=179.00000190734863,166.00000190734863 23 | AudioSynthWaveform waveform8; //xy=185,430 24 | AudioMixer4 mixer2; //xy=350.00000381469727,317.0000042915344 25 | AudioMixer4 mixer1; //xy=359.00000381469727,217.00000190734863 26 | AudioMixer4 mixer3; //xy=512.0000076293945,268.00000381469727 27 | AudioOutputI2S i2s1; //xy=663.0000076293945,185.00000190734863 28 | AudioConnection patchCord1(waveform6, 0, mixer2, 1); 29 | AudioConnection patchCord2(waveform5, 0, mixer2, 0); 30 | AudioConnection patchCord3(waveform4, 0, mixer1, 3); 31 | AudioConnection patchCord4(waveform7, 0, mixer2, 2); 32 | AudioConnection patchCord5(waveform2, 0, mixer1, 1); 33 | AudioConnection patchCord6(waveform3, 0, mixer1, 2); 34 | AudioConnection patchCord7(waveform1, 0, mixer1, 0); 35 | AudioConnection patchCord8(waveform8, 0, mixer2, 3); 36 | AudioConnection patchCord9(mixer2, 0, mixer3, 1); 37 | AudioConnection patchCord10(mixer1, 0, mixer3, 0); 38 | AudioConnection patchCord11(mixer3, 0, i2s1, 0); 39 | AudioConnection patchCord12(mixer3, 0, i2s1, 1); 40 | AudioControlSGTL5000 sgtl5000_1; //xy=562,81 41 | // GUItool: end automatically generated code 42 | 43 | 44 | 45 | #include "bleep_base.h" //Then we can add this line that we will still need 46 | 47 | //then you can declare any variables you want. 48 | unsigned long current_time; 49 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 50 | 51 | 52 | void setup() { 53 | start_bleep_base(); //run this first in setup 54 | 55 | //there's a lot we need to do in setup now but most of it is just copy paste. 56 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 57 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 58 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 59 | // It's usually the delay and reverb that hog it. 60 | AudioMemory(10); 61 | 62 | sgtl5000_1.enable(); //Turn the adapter board on 63 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 64 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 65 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 66 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 67 | 68 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 69 | // For headphones it's pretty loud at .4 70 | // There are lots of places we can change the final volume level. 71 | // For now lets set this one once and leave it alone. 72 | sgtl5000_1.volume(0.25); 73 | 74 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 75 | // If you're not using the line out don't worry about it. 76 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 77 | 78 | 79 | //This next group can be done anywhere in the code but we want to start things with these 80 | // values and change some of them in the loop. 81 | 82 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 83 | waveform1.begin(1, 100.0, WAVEFORM_SINE); //we set their amplitudes like this to approximate a ramp wave 84 | waveform2.begin(.9, 100.0, WAVEFORM_SINE); 85 | waveform3.begin(.8, 100.0, WAVEFORM_SINE); 86 | waveform4.begin(.7, 100.0, WAVEFORM_SINE); 87 | waveform5.begin(.6, 100.0, WAVEFORM_SINE); 88 | waveform6.begin(.5, 100.0, WAVEFORM_SINE); 89 | waveform7.begin(.4, 100.0, WAVEFORM_SINE); 90 | waveform8.begin(.3, 100.0, WAVEFORM_SINE); 91 | 92 | 93 | //The mixer has four inputs we can change the volume of 94 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 95 | // A gain of 1 means the output is the same as the input. 96 | // .5 would be half volume and 2 would be double 97 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 98 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 99 | float attenuate = .125; 100 | mixer1.gain(0, attenuate); 101 | mixer1.gain(1, attenuate); 102 | mixer1.gain(2, attenuate); 103 | mixer1.gain(3, attenuate); 104 | mixer2.gain(0, attenuate); 105 | mixer2.gain(1, attenuate); 106 | mixer2.gain(2, attenuate); 107 | mixer2.gain(3, attenuate); 108 | 109 | mixer3.gain(0, 1); 110 | mixer3.gain(1, 1); 111 | mixer3.gain(2, 1); 112 | mixer3.gain(3, 1); 113 | 114 | } //setup is over 115 | 116 | float xfade1, xfade2; //you can initialize variables here as long as you don't need them in setup. 117 | float freq[8]; 118 | 119 | void loop() { 120 | update_controls(); 121 | current_time = millis(); 122 | 123 | freq[1] = potRead(0) * 500.0; 124 | // it would be nice if we could do this with a "for" and use the increment to select the array of waveforms but the audio objects dont work like that easily. 125 | waveform1.frequency(freq[1]); 126 | waveform2.frequency(freq[1] * 2.0); 127 | waveform3.frequency(freq[1] * 3.0); 128 | waveform4.frequency(freq[1] * 4.0); 129 | 130 | waveform5.frequency(freq[1] * 5.0); 131 | waveform6.frequency(freq[1] * 6.0); 132 | waveform7.frequency(freq[1] * 7.0); 133 | waveform8.frequency(freq[1] * 8.0); 134 | 135 | 136 | /* 137 | xfade1 = potRead(0); 138 | xfade2 = 1.0 - xfade1; 139 | 140 | mixer1.gain(0, xfade1); 141 | mixer1.gain(1, xfade2); 142 | */ 143 | 144 | if (current_time - prev_time[0] > 50 && 1) { 145 | prev_time[0] = current_time; 146 | Serial.print("processor: "); 147 | Serial.print(AudioProcessorUsageMax()); 148 | Serial.print("% Memory: "); 149 | Serial.print(AudioMemoryUsageMax()); 150 | Serial.println(); 151 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 152 | AudioMemoryUsageMaxReset(); 153 | } 154 | 155 | }// loop is over 156 | -------------------------------------------------------------------------------- /Class-5/class_5_-_melody2_random_steps/class_5_-_melody2_random_steps.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=167,267 17 | AudioSynthWaveform waveform1; //xy=175,215 18 | AudioMixer4 mixer1; //xy=383,245 19 | AudioOutputI2S i2s1; //xy=591,244 20 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 21 | AudioConnection patchCord2(waveform1, 0, mixer1, 0); 22 | AudioConnection patchCord3(mixer1, 0, i2s1, 0); 23 | AudioConnection patchCord4(mixer1, 0, i2s1, 1); 24 | AudioControlSGTL5000 sgtl5000_1; //xy=484,355 25 | // GUItool: end automatically generated code 26 | 27 | #include "bleep_base.h" //Then we can add this line that we will still need 28 | 29 | //then you can declare any variables you want. 30 | unsigned long current_time; 31 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 32 | float freq[2]; 33 | //const is constant stored in flash mem aka program space 34 | const float chromatic[88] = {55.00000728, 58.27047791, 61.73542083, 65.40639999, 69.29566692, 73.4162017, 77.78175623, 82.40690014, 87.30706942, 92.49861792, 97.99887197, 103.8261881, 110.0000146, 116.5409558, 123.4708417, 130.8128, 138.5913338, 146.8324034, 155.5635124, 164.8138003, 174.6141388, 184.9972358, 195.9977439, 207.6523763, 220.0000291, 233.0819116, 246.9416833, 261.6255999, 277.1826676, 293.6648067, 311.1270248, 329.6276005, 349.2282776, 369.9944716, 391.9954878, 415.3047525, 440.0000581, 466.1638231, 493.8833665, 523.2511997, 554.3653352, 587.3296134, 622.2540496, 659.2552009, 698.4565551, 739.9889431, 783.9909755, 830.6095048, 880.0001162, 932.3276461, 987.7667329, 1046.502399, 1108.73067, 1174.659227, 1244.508099, 1318.510402, 1396.91311, 1479.977886, 1567.981951, 1661.219009, 1760.000232, 1864.655292, 1975.533466, 2093.004798, 2217.46134, 2349.318453, 2489.016198, 2637.020803, 2793.82622, 2959.955772, 3135.963901, 3322.438019, 3520.000464, 3729.310584, 3951.066931, 4186.009596, 4434.92268, 4698.636906, 4978.032395, 5274.041605, 5587.652439, 5919.911543, 6271.927802, 6644.876037, 7040.000927, 7458.621167, 7902.133861, 8372.019192}; 35 | // byte is the smallest 0-255 so i can save memory 36 | const byte major[65] = {1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24, 25, 27, 29, 30, 32, 34, 36, 37, 39, 41, 42, 44, 46, 48, 49, 51, 53, 54, 56, 58, 60, 61, 63, 65, 66, 68, 70, 72, 73, 75, 77, 78, 80, 82, 84, 85, 87, 89, 90, 92, 94, 96, 97, 99, 101, 102}; 37 | int melody1[8] = {15, 22, 12, 14, 22, 15, 17, 30}; 38 | int pos_a = 20; 39 | int pos_b = 50; 40 | int inc1; 41 | int major_inc1; 42 | int melody_rate; 43 | int direction1; 44 | int dice1, dice2, diceses3; 45 | 46 | void setup() { 47 | start_bleep_base(); //run this first in setup 48 | 49 | //there's a lot we need to do in setup now but most of it is just copy paste. 50 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 51 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 52 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 53 | // It's usually the delay and reverb that hog it. 54 | AudioMemory(10); 55 | 56 | sgtl5000_1.enable(); //Turn the adapter board on 57 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 58 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 59 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 60 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 61 | 62 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 63 | // For headphones it's pretty loud at .4 64 | // There are lots of places we can change the final volume level. 65 | // For now lets set this one once and leave it alone. 66 | sgtl5000_1.volume(0.25); 67 | 68 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 69 | // If you're not using the line out don't worry about it. 70 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 71 | 72 | 73 | //This next group can be done anywhere in the code but we want to start things with these 74 | // values and change some of them in the loop. 75 | 76 | //Notice we start by writing the object we want, then a period, then the function 77 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 78 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 79 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 80 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 81 | 82 | //The mixer has four inputs we can change the volume of 83 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 84 | // A gain of 1 means the output is the same as the input. 85 | // .5 would be half volume and 2 would be double 86 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 87 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 88 | mixer1.gain(0, .5); 89 | mixer1.gain(1, .5); 90 | mixer1.gain(2, 0); 91 | mixer1.gain(3, 0); 92 | 93 | inc1 = pos_a; //you can only set a variable equal to another in setup or loop. You cant do it in initialization section above 94 | } //setup is over 95 | 96 | void loop() { 97 | update_controls(); 98 | current_time = millis(); 99 | melody_rate = potRead(0) * 500.0; 100 | 101 | pos_a = potRead(1) * 50.0; 102 | pos_b = potRead(2) * 50.0; 103 | 104 | if (pos_a > pos_b) { 105 | direction1 = 1; 106 | } 107 | else { 108 | direction1 = 0; 109 | } 110 | 111 | if (current_time - prev_time[1] > melody_rate) { / 112 | prev_time[1] = current_time; 113 | 114 | if (direction1 == 1) { 115 | dice1 = random(0, 5); //(low value, high value) returns 0,1,2,3, or 4 the top value is not included but the bottom one is 116 | inc1 += dice1; //same as inc1 = inc1 + dice1 117 | if (inc1 > pos_a) { 118 | inc1 = pos_b; 119 | } 120 | } 121 | 122 | if (direction1 == 0) { 123 | dice2 = random(0, 4); //0,1,2, or 3 124 | inc1 -= dice2; 125 | 126 | if (inc1 < pos_a) { 127 | inc1 = pos_b; 128 | } 129 | } 130 | 131 | 132 | major_inc1 = major[inc1]; 133 | 134 | freq[0] = chromatic[major_inc1]; 135 | freq[1] = chromatic[major_inc1] / 2.01; 136 | waveform1.frequency(freq[0]); 137 | waveform2.frequency(freq[1]); 138 | 139 | } 140 | 141 | if (current_time - prev_time[2] > 100 && 1) { //&& is also. 0 means it wont happen, 1 will 142 | prev_time[2] = current_time; 143 | Serial.print("direction1 "); 144 | Serial.println(direction1); 145 | Serial.print("pos_a "); 146 | Serial.println(pos_a); 147 | Serial.print("pos_b "); 148 | Serial.println(pos_b); 149 | Serial.print("inc1 "); 150 | Serial.println(inc1); 151 | Serial.println(); 152 | 153 | } 154 | 155 | 156 | if (current_time - prev_time[0] > 500 && 0) { //&& is also. 0 means it wont happen, 1 will 157 | prev_time[0] = current_time; 158 | 159 | //Here we print out the usage of the audio library 160 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 161 | // If you're using too many block, jut increas the number up top untill you're over it by a few 162 | Serial.print("processor: "); 163 | Serial.print(AudioProcessorUsageMax()); 164 | Serial.print("% Memory: "); 165 | Serial.print(AudioMemoryUsageMax()); 166 | Serial.println(); 167 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 168 | AudioMemoryUsageMaxReset(); 169 | } 170 | 171 | }// loop is over 172 | -------------------------------------------------------------------------------- /Class-5/class_5_-_melody3_change_waveforms/class_5_-_melody3_change_waveforms.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform2; //xy=167,267 17 | AudioSynthWaveform waveform1; //xy=175,215 18 | AudioMixer4 mixer1; //xy=383,245 19 | AudioOutputI2S i2s1; //xy=591,244 20 | AudioConnection patchCord1(waveform2, 0, mixer1, 1); 21 | AudioConnection patchCord2(waveform1, 0, mixer1, 0); 22 | AudioConnection patchCord3(mixer1, 0, i2s1, 0); 23 | AudioConnection patchCord4(mixer1, 0, i2s1, 1); 24 | AudioControlSGTL5000 sgtl5000_1; //xy=484,355 25 | // GUItool: end automatically generated code 26 | 27 | #include "bleep_base.h" //Then we can add this line that we will still need 28 | 29 | //then you can declare any variables you want. 30 | unsigned long current_time; 31 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 32 | float freq[2]; 33 | //const is constant stored in flash mem aka program space 34 | const float chromatic[88] = {55.00000728, 58.27047791, 61.73542083, 65.40639999, 69.29566692, 73.4162017, 77.78175623, 82.40690014, 87.30706942, 92.49861792, 97.99887197, 103.8261881, 110.0000146, 116.5409558, 123.4708417, 130.8128, 138.5913338, 146.8324034, 155.5635124, 164.8138003, 174.6141388, 184.9972358, 195.9977439, 207.6523763, 220.0000291, 233.0819116, 246.9416833, 261.6255999, 277.1826676, 293.6648067, 311.1270248, 329.6276005, 349.2282776, 369.9944716, 391.9954878, 415.3047525, 440.0000581, 466.1638231, 493.8833665, 523.2511997, 554.3653352, 587.3296134, 622.2540496, 659.2552009, 698.4565551, 739.9889431, 783.9909755, 830.6095048, 880.0001162, 932.3276461, 987.7667329, 1046.502399, 1108.73067, 1174.659227, 1244.508099, 1318.510402, 1396.91311, 1479.977886, 1567.981951, 1661.219009, 1760.000232, 1864.655292, 1975.533466, 2093.004798, 2217.46134, 2349.318453, 2489.016198, 2637.020803, 2793.82622, 2959.955772, 3135.963901, 3322.438019, 3520.000464, 3729.310584, 3951.066931, 4186.009596, 4434.92268, 4698.636906, 4978.032395, 5274.041605, 5587.652439, 5919.911543, 6271.927802, 6644.876037, 7040.000927, 7458.621167, 7902.133861, 8372.019192}; 35 | // byte is the smallest 0-255 so i can save memory 36 | const byte major[65] = {1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24, 25, 27, 29, 30, 32, 34, 36, 37, 39, 41, 42, 44, 46, 48, 49, 51, 53, 54, 56, 58, 60, 61, 63, 65, 66, 68, 70, 72, 73, 75, 77, 78, 80, 82, 84, 85, 87, 89, 90, 92, 94, 96, 97, 99, 101, 102}; 37 | int melody1[8] = {15, 22, 12, 14, 22, 15, 17, 30}; 38 | int pos_a = 20; 39 | int pos_b = 50; 40 | int inc1; 41 | int major_inc1; 42 | int melody_rate; 43 | int direction1, prev_direction1; 44 | 45 | int dice1, dice2, diceses3; 46 | 47 | void setup() { 48 | start_bleep_base(); //run this first in setup 49 | 50 | //there's a lot we need to do in setup now but most of it is just copy paste. 51 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 52 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 53 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 54 | // It's usually the delay and reverb that hog it. 55 | AudioMemory(10); 56 | 57 | sgtl5000_1.enable(); //Turn the adapter board on 58 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 59 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 60 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 61 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 62 | 63 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 64 | // For headphones it's pretty loud at .4 65 | // There are lots of places we can change the final volume level. 66 | // For now lets set this one once and leave it alone. 67 | sgtl5000_1.volume(0.25); 68 | 69 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 70 | // If you're not using the line out don't worry about it. 71 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 72 | 73 | 74 | //This next group can be done anywhere in the code but we want to start things with these 75 | // values and change some of them in the loop. 76 | 77 | //Notice we start by writing the object we want, then a period, then the function 78 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 79 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 80 | waveform1.begin(1, 220.0, WAVEFORM_SINE); 81 | waveform2.begin(1, 440.0, WAVEFORM_SINE); 82 | 83 | //The mixer has four inputs we can change the volume of 84 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 85 | // A gain of 1 means the output is the same as the input. 86 | // .5 would be half volume and 2 would be double 87 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 88 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 89 | mixer1.gain(0, 1); 90 | mixer1.gain(1, 0); 91 | mixer1.gain(2, 0); 92 | mixer1.gain(3, 0); 93 | inc1 = pos_a; 94 | } //setup is over 95 | 96 | void loop() { 97 | update_controls(); 98 | current_time = millis(); 99 | melody_rate = potRead(0) * 500.0; 100 | 101 | pos_a = potRead(1) * 50.0; 102 | pos_b = potRead(2) * 50.0; 103 | 104 | prev_direction1 = direction1; //store what the value of direction1 was last loop 105 | 106 | if (pos_a > pos_b) { 107 | direction1 = 1; 108 | } 109 | else { 110 | direction1 = 0; 111 | } 112 | 113 | 114 | //changing waveforms resets the phase to 0, that is starts it over again 115 | // so we only want to do the once when the direction changes 116 | // This is just like how we only do something the one loop that a button is being pressed. 117 | 118 | if (prev_direction1 != direction1) { 119 | 120 | if (direction1 == 1) { 121 | waveform1.begin(WAVEFORM_SAWTOOTH); 122 | } 123 | if (direction1 == 0) { 124 | waveform1.begin(WAVEFORM_SINE); 125 | } 126 | } 127 | 128 | if (current_time - prev_time[1] > melody_rate) { 129 | prev_time[1] = current_time; 130 | 131 | if (direction1 == 1) { 132 | dice1 = random(0, 5); 133 | inc1 += dice1; 134 | if (inc1 > pos_a) { 135 | inc1 = pos_b; 136 | } 137 | } 138 | 139 | if (direction1 == 0) { 140 | dice2 = random(0, 4); 141 | inc1 -= dice2; 142 | 143 | if (inc1 < pos_a) { 144 | inc1 = pos_b; 145 | } 146 | } 147 | 148 | 149 | major_inc1 = major[inc1]; 150 | 151 | freq[0] = chromatic[major_inc1]; 152 | freq[1] = chromatic[major_inc1] / 2.01; 153 | 154 | waveform1.frequency(freq[0]); 155 | waveform2.frequency(freq[1]); 156 | 157 | } 158 | 159 | if (current_time - prev_time[2] > 100 && 1) { //&& is also. 0 means it wont happen, 1 will 160 | prev_time[2] = current_time; 161 | Serial.print("direction1 "); 162 | Serial.println(direction1); 163 | Serial.print("pos_a "); 164 | Serial.println(pos_a); 165 | Serial.print("pos_b "); 166 | Serial.println(pos_b); 167 | Serial.print("inc1 "); 168 | Serial.println(inc1); 169 | Serial.println(); 170 | 171 | } 172 | 173 | 174 | if (current_time - prev_time[0] > 500 && 0) { //&& is also. 0 means it wont happen, 1 will 175 | prev_time[0] = current_time; 176 | 177 | //Here we print out the usage of the audio library 178 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 179 | // If you're using too many block, jut increas the number up top untill you're over it by a few 180 | Serial.print("processor: "); 181 | Serial.print(AudioProcessorUsageMax()); 182 | Serial.print("% Memory: "); 183 | Serial.print(AudioMemoryUsageMax()); 184 | Serial.println(); 185 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 186 | AudioMemoryUsageMaxReset(); 187 | } 188 | 189 | }// loop is over 190 | -------------------------------------------------------------------------------- /Class-5/smoothing_example_re_Marcel/smoothing_example_re_Marcel.ino: -------------------------------------------------------------------------------- 1 | unsigned long current_time; 2 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 3 | int raw_reading; 4 | int smoothed_reading; 5 | int mapped_output; 6 | 7 | void setup() { 8 | // put your setup code here, to run once: 9 | analogReadResolution(10); 10 | } 11 | 12 | void loop() { 13 | current_time = millis(); 14 | 15 | if (current_time - prev_time[1] > 100) { // chage frequence ever 200 milliseconds 16 | prev_time[1] = current_time; 17 | raw_reading = analogRead(A2); 18 | smoothed_reading = (0, 71, raw_reading); 19 | mapped_output = map(smoothed_reading, 20, 600, 0, 1000); 20 | } 21 | 22 | if (current_time - prev_time[2] > 50) { // chage frequence ever 200 milliseconds 23 | prev_time[2] = current_time; 24 | Serial.print(mapped_output); 25 | Serial.print(" "); 26 | Serial.println(smoothed_reading); 27 | } 28 | 29 | 30 | 31 | } 32 | 33 | 34 | 35 | //based on https://playground.arduino.cc/Main/DigitalSmooth/ 36 | // This function continuously samples an input and puts it in an array that is "samples" in length. 37 | // This array has a new "raw_in" value added to it each time "smooth" is called and an old value is removed 38 | // It throws out the top and bottom 15% of readings and averages the rest 39 | 40 | #define maxarrays 3 //max number of different variables to smooth 41 | #define maxsamples 1000 //max number of points to sample and 42 | //reduce these numbers to save RAM 43 | 44 | unsigned int smoothArray[maxarrays][maxsamples]; 45 | 46 | // sel should be a unique number for each occurrence 47 | // samples should be an odd number greater that 7. It's the length of the array. The larger the more smooth but less responsive 48 | // raw_in is the input. positive numbers in and out only. 49 | 50 | unsigned int smooth(byte sel, unsigned int samples, unsigned int raw_in) { 51 | int j, k, temp, top, bottom; 52 | long total; 53 | static int i[maxarrays]; 54 | static int sorted[maxarrays][maxsamples]; 55 | boolean done; 56 | 57 | i[sel] = (i[sel] + 1) % samples; // increment counter and roll over if necessary. - % (modulo operator) rolls over variable 58 | smoothArray[sel][i[sel]] = raw_in; // input new data into the oldest slot 59 | 60 | for (j = 0; j < samples; j++) { // transfer data array into anther array for sorting and averaging 61 | sorted[sel][j] = smoothArray[sel][j]; 62 | } 63 | 64 | done = 0; // flag to know when we're done sorting 65 | while (done != 1) { // simple swap sort, sorts numbers from lowest to highest 66 | done = 1; 67 | for (j = 0; j < (samples - 1); j++) { 68 | if (sorted[sel][j] > sorted[sel][j + 1]) { // numbers are out of order - swap 69 | temp = sorted[sel][j + 1]; 70 | sorted[sel] [j + 1] = sorted[sel][j] ; 71 | sorted[sel] [j] = temp; 72 | done = 0; 73 | } 74 | } 75 | } 76 | 77 | // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom 78 | bottom = max(((samples * 15) / 100), 1); 79 | top = min((((samples * 85) / 100) + 1 ), (samples - 1)); // the + 1 is to make up for asymmetry caused by integer rounding 80 | k = 0; 81 | total = 0; 82 | for ( j = bottom; j < top; j++) { 83 | total += sorted[sel][j]; // total remaining indices 84 | k++; 85 | } 86 | return total / k; // divide by number of samples 87 | } 88 | -------------------------------------------------------------------------------- /Class-6/class_6_map_simple_example/class_6_map_simple_example.ino: -------------------------------------------------------------------------------- 1 | //quickly showing how to use map() to change the range of pots 2 | 3 | // https://www.arduino.cc/reference/en/language/functions/math/map/ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // GUItool: begin automatically generated code 11 | AudioSynthWaveform waveform2; //xy=197,225 12 | AudioSynthWaveform waveform1; //xy=220,180 13 | AudioMixer4 mixer1; //xy=457,225 14 | AudioOutputI2S i2s1; //xy=681,207 15 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 16 | AudioConnection patchCord4(waveform1, 0, mixer1, 0); 17 | AudioConnection patchCord5(mixer1, 0, i2s1, 0); 18 | AudioConnection patchCord6(mixer1, 0, i2s1, 1); 19 | AudioControlSGTL5000 sgtl5000_1; //xy=573,341 20 | // GUItool: end automatically generated code 21 | 22 | 23 | 24 | #include "bleep_base.h" //Then we can add this line that we will still need 25 | 26 | //then you can declare any variables you want. 27 | unsigned long current_time; 28 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 29 | float note_read1; 30 | float freq[4]; 31 | float temp_pot[4]; 32 | 33 | void setup() { 34 | start_bleep_base(); //run this first in setup 35 | 36 | //there's a lot we need to do in setup now but most of it is just copy paste. 37 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 38 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 39 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 40 | // It's usually the delay and reverb that hog it. 41 | AudioMemory(100); 42 | 43 | sgtl5000_1.enable(); //Turn the adapter board on 44 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 45 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 46 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 47 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 48 | 49 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 50 | // For headphones it's pretty loud at .4 51 | // There are lots of places we can change the final volume level. 52 | // For now lets set this one once and leave it alone. 53 | sgtl5000_1.volume(0.25); 54 | 55 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 56 | // If you're not using the line out don't worry about it. 57 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 58 | 59 | 60 | //This next group can be done anywhere in the code but we want to start things with these 61 | // values and change some of them in the loop. 62 | 63 | //Notice we start by writing the object we want, then a period, then the function 64 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 65 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 66 | waveform1.begin(1, 220.0, WAVEFORM_SQUARE); 67 | waveform2.begin(1, 440.0, WAVEFORM_SAWTOOTH); 68 | 69 | //The mixer has four inputs we can change the volume of 70 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 71 | // A gain of 1 means the output is the same as the input. 72 | // .5 would be half volume and 2 would be double 73 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 74 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 75 | mixer1.gain(0, .5); 76 | mixer1.gain(1, .5); 77 | mixer1.gain(2, 0); 78 | mixer1.gain(3, 0); 79 | 80 | 81 | } //setup is over 82 | 83 | void loop() { 84 | update_controls(); 85 | current_time = millis(); 86 | 87 | 88 | int raw1 = potReadRaw(0); //returns 0-1023 89 | if (raw1<512){ //512 is the middle of the pot o tis only happens when its on the right side 90 | freq[0] = map(raw1,0,512,200,1000); //map(input,origial low,origial high, desired low,desired high 91 | } 92 | if (raw1>=512){ 93 | freq[0] = map(raw1,512,1023,1000,1200); 94 | } 95 | 96 | 97 | 98 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 99 | if (current_time - prev_time[0] > 50) { 100 | prev_time[0] = current_time; 101 | 102 | Serial.println(freq[0]); 103 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 104 | AudioMemoryUsageMaxReset(); 105 | } 106 | 107 | }// loop is over 108 | -------------------------------------------------------------------------------- /Class-7/mapping_and_expo/mapping_and_expo.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform1; //xy=168,208 17 | AudioSynthWaveform waveform2; //xy=173,279 18 | AudioAnalyzePeak peak1; //xy=365,125 19 | AudioAnalyzePeak peak2; //xy=427,178 20 | AudioMixer4 mixer1; //xy=553,279 21 | AudioOutputI2S i2s1; //xy=718,282 22 | AudioConnection patchCord1(waveform1, 0, mixer1, 0); 23 | AudioConnection patchCord2(waveform1, peak1); 24 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 25 | AudioConnection patchCord4(waveform2, peak2); 26 | AudioConnection patchCord5(mixer1, 0, i2s1, 0); 27 | AudioConnection patchCord6(mixer1, 0, i2s1, 1); 28 | AudioControlSGTL5000 sgtl5000_1; //xy=611,393 29 | // GUItool: end automatically generated code 30 | 31 | 32 | 33 | #include "bleep_base.h" //Then we can add this line that we will still need 34 | 35 | //then you can declare any variables you want. 36 | unsigned long current_time; 37 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 38 | float lfo1, lfo2, lfo3; 39 | float freq1, temp1, temp2; 40 | void setup() { 41 | start_bleep_base(); //run this first in setup 42 | 43 | //there's a lot we need to do in setup now but most of it is just copy paste. 44 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 45 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 46 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 47 | // It's usually the delay and reverb that hog it. 48 | AudioMemory(10); 49 | 50 | sgtl5000_1.enable(); //Turn the adapter board on 51 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 52 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 53 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 54 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 55 | 56 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 57 | // For headphones it's pretty loud at .4 58 | // There are lots of places we can change the final volume level. 59 | // For now lets set this one once and leave it alone. 60 | sgtl5000_1.volume(0.25); 61 | 62 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 63 | // If you're not using the line out don't worry about it. 64 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 65 | 66 | 67 | //This next group can be done anywhere in the code but we want to start things with these 68 | // values and change some of them in the loop. 69 | 70 | //Notice we start by writing the object we want, then a period, then the function 71 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 72 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 73 | waveform1.begin(1, 0.2, WAVEFORM_SINE); 74 | waveform2.begin(1, 0.01, WAVEFORM_SINE); 75 | 76 | //The mixer has four inputs we can change the volume of 77 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 78 | // A gain of 1 means the output is the same as the input. 79 | // .5 would be half volume and 2 would be double 80 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 81 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 82 | mixer1.gain(0, 1); 83 | mixer1.gain(1, 0); 84 | mixer1.gain(2, 0); 85 | mixer1.gain(3, 0); 86 | 87 | } //setup is over 88 | 89 | void loop() { 90 | update_controls(); 91 | current_time = millis(); 92 | 93 | 94 | //this is the confusing way to do it with floats 95 | temp1 = potRead(0); //0-1.0 96 | if (temp1 < .5) {//if its on one side do this 97 | //temp 1 is going from 0-.5 but we want it from 50-250 98 | // multiply by 2 to get it to 0-1 99 | // by 200 to get to 0-200 100 | // add 50 to get 50-250 101 | freq1 = (temp1 * 2.0 * 200.0) + 50.0; 102 | } 103 | if (temp1 >= .5) { 104 | //on the other side 105 | //we want to start at 250 as thats where the other left off so add 250 106 | //temp is starting at .5 so subtract that and get it to 0-1.0 by multiplying by 2 107 | //we want it to go to 1000 so multiply by that 108 | freq1 = (((temp1 - .5) * 2.0) * 1000.0) + 250.0; 109 | } 110 | 111 | //or we could use map but it only takes integers 112 | //map(input value, fromLow, fromHigh, toLow, toHigh) 113 | 114 | int low_point = 200 115 | int middle_point = 800 116 | int high_point = 1200 117 | 118 | temp2 = potRead(0) * 1000; //0 - 10000 119 | if (temp2 < 500) {//on one side 120 | //we start at 0 and go to 500 on this side but want 200-800 121 | freq1 = map(temp2, 0, 500, low_point, middle_point); 122 | } 123 | if (temp2 >= 500) { 124 | //now we start at 500 and get to 1000. 800 is where the other left off 125 | freq1 = map(temp2, 500, 1000, middle_point, high_point); 126 | } 127 | 128 | 129 | //another way to map is with an exponential converter 130 | // for audio, exponential curves sound more natural. 131 | // Pretty much every volume knob you use has an exponential response, with the lower numbers going by more quickly than the higher ones 132 | // Heres a quick graph. You start and end at the same place but take a different route http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoeF4yKS8oMTBeMSkiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjAsImVxIjoiKHheMykvKDEwXjIpIiwiY29sb3IiOiIjMzkwOUQ5In0seyJ0eXBlIjowLCJlcSI6Iih4XjQpLygxMF4zKSIsImNvbG9yIjoiI0ZGODAwMCJ9LHsidHlwZSI6MCwiZXEiOiJ4IiwiY29sb3IiOiIjRkYwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMCIsIjEwIiwiMCIsIjEwIl19XQ-- 133 | 134 | // to do this I mad a quick function at the bottom, outside the loop 135 | // expo_converter(input for 0-1.0, high value you want to get to, curve); 136 | // if curve is 1 its linear, <1 log >1 expo 137 | 138 | expo1 = expo_converter(potRead(0), 1000, 2); 139 | 140 | 141 | waveform1.frequency(freq1); 142 | 143 | if (current_time - prev_time[0] > 20) { 144 | prev_time[0] = current_time; 145 | 146 | //prints the linear and exponential response from the same pot 147 | Serial.print(temp2); 148 | Serial.print(" "); 149 | Serial.println(expo1); 150 | 151 | } 152 | 153 | 154 | 155 | }// loop is over 156 | 157 | 158 | //input 0-1, returns 0-max in expo curve 159 | //max is 0 to whatever 160 | //if curve is 1 its linear, <1 log >1 expo 161 | 162 | float expo_converter(float input, float max1, float curve) { 163 | //powf is a more effeinct power for floats 164 | // powf(base, exponent) 165 | float ex1 = powf((1.0 - input) * max1, curve) / powf(max1, curve - 1.0); 166 | return ex1; 167 | } 168 | -------------------------------------------------------------------------------- /Class-7/more_leds/more_leds.ino: -------------------------------------------------------------------------------- 1 | // talking to more LEDs using the header and reviewing for loops 2 | // LED info here https://github.com/BleepLabs/dadageek-Feb21/wiki/Using-LEDs-on-the-Bleep-Base 3 | 4 | 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // GUItool: begin automatically generated code 14 | AudioSynthWaveform waveform1; //xy=168,208 15 | AudioSynthWaveform waveform2; //xy=173,279 16 | AudioAnalyzePeak peak1; //xy=365,125 17 | AudioAnalyzePeak peak2; //xy=427,178 18 | AudioMixer4 mixer1; //xy=553,279 19 | AudioOutputI2S i2s1; //xy=718,282 20 | AudioConnection patchCord1(waveform1, 0, mixer1, 0); 21 | AudioConnection patchCord2(waveform1, peak1); 22 | AudioConnection patchCord3(waveform2, 0, mixer1, 1); 23 | AudioConnection patchCord4(waveform2, peak2); 24 | AudioConnection patchCord5(mixer1, 0, i2s1, 0); 25 | AudioConnection patchCord6(mixer1, 0, i2s1, 1); 26 | AudioControlSGTL5000 sgtl5000_1; //xy=611,393 27 | // GUItool: end automatically generated code 28 | 29 | 30 | 31 | #include "bleep_base.h" //Then we can add this line that we will still need 32 | 33 | //then you can declare any variables you want. 34 | unsigned long current_time; 35 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 36 | float lfo1, lfo2, lfo3; 37 | 38 | void setup() { 39 | start_bleep_base(); //run this first in setup 40 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 41 | // It's usually the delay and reverb that hog it. 42 | AudioMemory(10); 43 | 44 | sgtl5000_1.enable(); //Turn the adapter board on 45 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 46 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 47 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 48 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 49 | 50 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 51 | // For headphones it's pretty loud at .4 52 | // There are lots of places we can change the final volume level. 53 | // For now lets set this one once and leave it alone. 54 | sgtl5000_1.volume(0.25); 55 | 56 | //The line out has a separate level control but it's not meant to be adjusted like the volume function above. 57 | // If you're not using the line out don't worry about it. 58 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 59 | 60 | 61 | //This next group can be done anywhere in the code but we want to start things with these 62 | // values and change some of them in the loop. 63 | 64 | //Notice we start by writing the object we want, then a period, then the function 65 | // begin(volume from 0.0-1.0 , frequency , shape of oscillator) 66 | // See the tool for more info https://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform 67 | waveform1.begin(1, 0.2, WAVEFORM_SINE); 68 | waveform2.begin(1, 0.01, WAVEFORM_SINE); 69 | 70 | //The mixer has four inputs we can change the volume of 71 | // gain.(channel from 0 to 3, gain from 0.0 to a large number) 72 | // A gain of 1 means the output is the same as the input. 73 | // .5 would be half volume and 2 would be double 74 | // Since we have two oscillators coming in that are already "1" We should take them down by half so we don't clip. 75 | // If you go over "1" The top or bottom of the wave is just slammed against a wall 76 | mixer1.gain(0, 1); 77 | mixer1.gain(1, 0); 78 | mixer1.gain(2, 0); 79 | mixer1.gain(3, 0); 80 | 81 | } //setup is over 82 | 83 | void loop() { 84 | update_controls(); 85 | current_time = millis(); 86 | 87 | if (current_time - prev_time[1] > 10) { 88 | prev_time[1] = current_time; 89 | lfo1 += .02; 90 | if (lfo1 >= 1.0) { 91 | lfo1 = 0; 92 | } 93 | 94 | if (peak1.available()) { //read the level of the audio waveforms and return 0-1.0 95 | lfo2 = peak1.read(); 96 | } 97 | if (peak2.available()) { 98 | lfo3 = peak2.read(); 99 | } 100 | 101 | 102 | for (int ledj = 2; ledj < 8; ledj++) { //start at the 2nd led and go to the 7th. The first 2 leds are on the bleep base 103 | 104 | //ledj is incrementing so use it to make each LED a different color. 105 | // since this is all happening in the for loop the lights will be static though. Nothing outside the loop is changing it 106 | float hue1 = (ledj - 2) * .15; 107 | 108 | float hue2 = hue1 + lfo1; //lfo is going at it's own rate, outside of this for loop so the lights will change 109 | if (hue2 >= 1.0) { 110 | //rather than going back to 0, we subtract 1.0 111 | // that way it cleanly goes around in a loop as thats how the hue rainbow works 112 | // if it's 1.2, it comes out .2 113 | hue2 -= 1.0; 114 | } 115 | set_LED(ledj, hue2, lfo2, lfo3); //(led to change, hue, satuuration,brightness) 116 | } 117 | 118 | 119 | LEDs.show(); 120 | 121 | } 122 | 123 | 124 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 125 | if (current_time - prev_time[0] > 500) { 126 | prev_time[0] = current_time; 127 | 128 | //Here we print out the usage of the audio library 129 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 130 | // If you're using too many block, jut increas the number up top untill you're over it by a few 131 | Serial.print("processor: "); 132 | Serial.print(AudioProcessorUsageMax()); 133 | Serial.print("% Memory: "); 134 | Serial.print(AudioMemoryUsageMax()); 135 | Serial.println(); 136 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 137 | AudioMemoryUsageMaxReset(); 138 | } 139 | 140 | }// loop is over 141 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base/sampler2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * tested on JM's hardware and works 10-16-20 3 | */ 4 | 5 | #include "sampler2.h" 6 | #include "arm_math.h" 7 | #include "utility/dspinst.h" 8 | 9 | 10 | 11 | void AudioSampler::update(void) 12 | { 13 | audio_block_t *ab_left; 14 | audio_block_t *ab_right; 15 | 16 | short *bpl, *bpr, *end; 17 | int32_t val1, val2, val3; 18 | short tempf; 19 | 20 | 21 | if (tone_amp == 0 || playing == 0) return; 22 | ab_left = allocate(); 23 | ab_right = allocate(); 24 | 25 | if (ab_left) { 26 | bpl = ab_left->data; 27 | bpr = ab_right->data; 28 | 29 | 30 | for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { 31 | 32 | if (rev == 0) { 33 | 34 | if (playing == 0) { 35 | *bpl++ = (short)(0); 36 | *bpr++ = (short)(0); 37 | } 38 | 39 | if (playing == 1) { 40 | pindex = index; 41 | index = tone_phase >> 23; //23 is 256 //changing causes rate reduction 42 | //Serial.println(index); 43 | 44 | if (pindex > 128 && index < 128) { //did it wrap around 45 | fpos += 256; // this is fixed its the max size of index 46 | get = 1; 47 | } 48 | 49 | if (fpos + index > sample_len ) { 50 | if (looping == 1) { 51 | fpos = mod_start_pos; 52 | index = 0; 53 | tone_phase = 0; 54 | get = 1; 55 | loop_trig1 = !loop_trig1; 56 | } 57 | if (looping == 0) { 58 | playing = 0; 59 | } 60 | 61 | } 62 | 63 | if (fpos + index > mod_start_pos + end_mod && end_mod_en == 1) { 64 | fpos = mod_start_pos; 65 | index = 0; 66 | tone_phase = 0; 67 | get = 0; 68 | bankshift = 0; 69 | bankoff = 0; 70 | if (looping == 1) { 71 | loop_trig1 = !loop_trig1; 72 | } 73 | if (looping == 0) { 74 | playing = 0; 75 | } 76 | } 77 | 78 | if (get == 1) { 79 | get = 0; 80 | //gfd = micros() - gfcm; 81 | //gfcm = micros(); 82 | uint32_t actualget = start_pos + (fpos * 4); 83 | 84 | //if (SerialFlash.ready() == 1) { //seems to always be ready untill its crashed 85 | AudioStartUsingSPI(); 86 | SerialFlash.read(actualget, in8, buffrl); 87 | AudioStopUsingSPI(); 88 | 89 | 90 | js = 0; 91 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 92 | sample_left_A[js] = (in8[j + 1] << 8) | (in8[j]); 93 | sample_right_A[js] = (in8[j + 3] << 8) | (in8[j + 2]); 94 | js++; 95 | } 96 | 97 | } 98 | 99 | scale = (tone_phase >> 7) & 0xFFFF; 100 | 101 | val1 = *(sample_left_A + index ); 102 | val2 = *(sample_left_A + (index + 1) ); 103 | val2 *= scale; 104 | val1 *= 0xFFFF - scale; 105 | val3 = (val1 + val2) >> 16; 106 | *bpl++ = (short)((val3 * tone_amp) >> 15); 107 | 108 | val1 = *(sample_right_A + index ); 109 | val2 = *(sample_right_A + (index + 1) ); 110 | val2 *= scale; 111 | val1 *= 0xFFFF - scale; 112 | val3 = (val1 + val2) >> 16; 113 | *bpr++ = (short)((val3 * tone_amp) >> 15); 114 | 115 | tone_phase += tone_incr; 116 | tone_phase &= 0x7fffffff; 117 | 118 | 119 | } 120 | } 121 | 122 | 123 | if (rev == 1) { 124 | 125 | 126 | if (playing == 0) { 127 | *bpl++ = (short)(0); 128 | *bpr++ = (short)(0); 129 | } 130 | 131 | if (playing == 1) { 132 | pindex = index; 133 | index = tone_phase >> 23; 134 | revindex = (index - 255) * -1; 135 | bankoff = 0; 136 | 137 | if (pindex > 128 && index < 128) { 138 | fpos -= (256); 139 | 140 | get = 1; 141 | 142 | 143 | } 144 | 145 | if (fpos < 0) { 146 | fpos = sample_len; 147 | index = 0; 148 | tone_phase = 0; 149 | get = 1; 150 | //Serial.println("end"); 151 | if (looping == 0) { 152 | playing = 0; 153 | } 154 | if (looping == 1) { 155 | loop_trig1 = !loop_trig1; 156 | } 157 | 158 | } 159 | 160 | if (get == 1) { 161 | get = 0; 162 | // uint32_t tt = micros(); 163 | uint32_t rev_sactualget = rev_start + (fpos * 4); 164 | //Serial.print("Rag "); 165 | // Serial.println(rev_sactualget); 166 | // if (SerialFlash.ready() == 1) { 167 | AudioStartUsingSPI(); 168 | SerialFlash.read(rev_sactualget, in8, buffrl); 169 | AudioStopUsingSPI(); 170 | 171 | js = 0; 172 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 173 | sample_left_A[js] = (in8[j + 1] << 8) | (in8[j]); 174 | sample_right_A[js] = (in8[j + 3] << 8) | (in8[j + 2]); 175 | js++; 176 | } 177 | 178 | } 179 | 180 | scale = (tone_phase >> 7) & 0xFFFF; 181 | 182 | val1 = *(sample_left_A + revindex + 1 + bankoff); 183 | val2 = *(sample_left_A + (revindex ) + bankoff); 184 | val2 *= scale; 185 | val1 *= 0xFFFF - scale; 186 | val3 = (val1 + val2) >> 16; 187 | *bpl++ = (short)((val3 * tone_amp) >> 15); 188 | 189 | val1 = *(sample_right_A + revindex + 1 + bankoff); 190 | val2 = *(sample_right_A + revindex + bankoff); 191 | val2 *= scale; 192 | val1 *= 0xFFFF - scale; 193 | val3 = (val1 + val2) >> 16; 194 | *bpr++ = (short)((val3 * tone_amp) >> 15); 195 | 196 | tone_phase += tone_incr; 197 | tone_phase &= 0x7fffffff; 198 | 199 | } 200 | } 201 | } 202 | 203 | transmit(ab_left, 0); 204 | transmit(ab_right, 1); 205 | 206 | release(ab_left); 207 | release(ab_right); 208 | 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base/sampler2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tested on JM's hardware and works 10-16-20 3 | */ 4 | 5 | #ifndef synth_sampler_h_ 6 | #define synth_sampler_h_ 7 | 8 | #include "Arduino.h" 9 | #include "AudioStream.h" 10 | #include "arm_math.h" 11 | #include 12 | #include "spi_interrupt.h" 13 | 14 | 15 | #define AUDIO_SAMPLE_RATE_ROUNDED (44118) 16 | 17 | 18 | class AudioSampler : 19 | public AudioStream 20 | { 21 | 22 | public: 23 | AudioSampler(void) : 24 | AudioStream(0, NULL), tone_amp(0), tone_freq(0), 25 | tone_width(0.25), tone_incr(0), 26 | looping(0), playing(0) 27 | { 28 | } 29 | 30 | void frequency(float t_freq) { 31 | t_freq = norm * t_freq; 32 | if (t_freq < 0.0) t_freq = 0.0; 33 | else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) t_freq = AUDIO_SAMPLE_RATE_EXACT / 2; 34 | tone_incr = (t_freq * (0x80000000LL / AUDIO_SAMPLE_RATE_EXACT)) + 0.5; 35 | } 36 | 37 | void amplitude(float n) { // 0 to 1.0 38 | if (n < 0) n = 0; 39 | else if (n > 1.0) n = 1.0; 40 | if ((tone_amp == 0) && n) { 41 | // reset the phase when the amplitude was zero 42 | // and has now been increased. 43 | tone_phase = 0; 44 | } 45 | // set new magnitude 46 | tone_amp = n * 32767.0; 47 | } 48 | 49 | void begin(float t_amp, float t_freq, uint32_t s_pos, uint32_t len) { 50 | amplitude(t_amp); 51 | frequency(t_freq); 52 | sample_len = len; 53 | start_pos = s_pos; 54 | end_mod = len; 55 | mod_start_pos = 0; 56 | get = 0; 57 | } 58 | 59 | void sample_loop(int bb) { 60 | looping = bb; 61 | } 62 | 63 | void sample_play_loc(uint32_t s_pos, uint32_t len) { 64 | 65 | if (rev == 0) { 66 | fpos = 0; 67 | sample_len = len; 68 | start_pos = s_pos; //44 BYTES IN WAVE HEADER 69 | end_mod = len; 70 | index = 0; 71 | tone_phase = 0; 72 | get = 0; 73 | bankshift = 0; 74 | bankoff = 0; 75 | 76 | 77 | AudioStartUsingSPI(); 78 | SerialFlash.read(start_pos + (fpos * 4), in8b, buffrl); 79 | AudioStopUsingSPI(); 80 | 81 | js = 0; 82 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 83 | int16_t new_left = (in8b[j + 1] << 8) | (in8b[j]); 84 | int16_t new_right = (in8b[j + 3] << 8) | (in8b[j + 2]); 85 | sample_left_A[js] = new_left; 86 | sample_right_A[js] = new_right; 87 | js++; 88 | } 89 | 90 | playing = 1; 91 | 92 | } 93 | 94 | if (rev == 1) { 95 | sample_len = len; 96 | rev_start = s_pos ; 97 | fpos = len; 98 | rev_end = s_pos; 99 | rev_mod_start_pos = rev_start; 100 | index = 0; 101 | tone_phase = 0; 102 | get = 0; 103 | bankshift = 3; 104 | bankoff = bankshift << 8; 105 | // Serial.print("rev_start "); Serial.println(rev_start); 106 | // Serial.print("rev_end "); Serial.println(rev_end); 107 | // Serial.println(); 108 | playing = 1; 109 | 110 | } 111 | 112 | } 113 | 114 | 115 | 116 | void sample_stop() { 117 | playing = 0; 118 | } 119 | 120 | uint16_t sample_status() { 121 | return playing; 122 | } 123 | 124 | void sample_reverse(byte bb) { 125 | rev = bb; 126 | if (rev != prev_rev) { 127 | get = 1; 128 | } 129 | prev_rev = bb; 130 | //fpos = sample_len; 131 | 132 | } 133 | 134 | uint32_t sample_start_pos(float pd) { 135 | mod_start_pos = pd * (sample_len - 256); 136 | return rev_mod_start_pos; 137 | } 138 | 139 | uint32_t sample_play_len(float pd) { 140 | //pd=(pd*-1.00)+1.00; 141 | if (pd > 0) { 142 | end_mod_en = 1; 143 | end_mod = (pd * sample_len) + 256; 144 | } 145 | if (pd == 0) { 146 | end_mod_en = 0; 147 | } 148 | return end_mod; 149 | } 150 | 151 | uint32_t sample_loc(void) { 152 | uint32_t a = (uint32_t)index; 153 | return sample_address + a; 154 | } 155 | 156 | uint32_t revstart() { 157 | return rev_start; 158 | } 159 | 160 | uint32_t revend() { 161 | return rev_end; 162 | } 163 | 164 | byte loop_trig() { 165 | return loop_trig1; 166 | } 167 | 168 | uint32_t transfer_time() { 169 | return gfd; 170 | } 171 | 172 | virtual void update(void); 173 | 174 | private: 175 | #define SPI_SIZE (256) // how many 16b samples in each channel 176 | //2048 35ms single sample 177 | uint32_t gfcm, gfd; 178 | float norm = 86.1679 * 2; //normal playback speed 179 | 180 | short tone_amp; 181 | short tone_freq; 182 | uint32_t tone_phase; 183 | uint32_t index_assume; 184 | int32_t rev_start, rev_end; 185 | uint32_t tone_width; 186 | short sample; 187 | // volatile prevents the compiler optimizing out the frequency function 188 | volatile uint32_t tone_incr; 189 | short tone_type; 190 | const int16_t *arbdata; 191 | //int16_t *sfsample; 192 | //int16_t *sfsample16; 193 | int16_t js; 194 | uint32_t sf_pos; 195 | uint32_t sample_address; 196 | uint32_t sample_len, start_pos, mod_start_pos, end_mod, rev_mod_start_pos; 197 | char in8[(SPI_SIZE * 4) + 8]; 198 | char in8b[(SPI_SIZE * 4) + 8]; 199 | 200 | int16_t sample_left_A[(SPI_SIZE) + 2]; 201 | int16_t sample_right_A[(SPI_SIZE) + 2]; 202 | 203 | uint16_t get, end_flag; 204 | const uint16_t buffrl = (SPI_SIZE * 4) + 8; 205 | uint16_t pindex; 206 | uint32_t index, scale, end_mod_en; 207 | int32_t revindex = 256; 208 | int32_t fpos, blocknum; 209 | uint16_t looping, playing, rev, bankoff; 210 | int16_t bankshift, bankswitch; 211 | byte loop_trig1; 212 | byte prev_rev; 213 | }; 214 | 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base/sampler_helpers2.h: -------------------------------------------------------------------------------- 1 | //this block is all sampler stuff and can be left alone 2 | #define getsize AUDIO_BLOCK_SAMPLES*2 3 | uint32_t rec_size = (sfblocks * 0x10000); 4 | int16_t rec_target, foffset, mode_timer_latch, rec_mode, mode, prev_bank_sel; 5 | uint32_t bankstart[number_of_banks]; 6 | uint32_t samplelen[number_of_banks]; 7 | byte bank_status[number_of_banks]; 8 | uint32_t sfaddress, address; 9 | //end 10 | 11 | int32_t prev[12]; 12 | 13 | void save_sample_length(uint16_t slot, uint32_t to_save) { 14 | int16_t startee = slot * 4; 15 | EEPROM.write(startee, to_save >> 24); 16 | EEPROM.write(startee + 1, to_save >> 16); 17 | EEPROM.write(startee + 2, to_save >> 8); 18 | EEPROM.write(startee + 3, to_save & 0xFF); 19 | } 20 | 21 | uint32_t recall_sample_length(uint16_t slot) { 22 | int16_t startee = slot * 4; 23 | byte b4 = EEPROM.read(startee); 24 | byte b3 = EEPROM.read(startee + 1); 25 | byte b2 = EEPROM.read(startee + 2); 26 | byte b1 = EEPROM.read(startee + 3); 27 | uint32_t lt = (b4 << 24) | (b3 << 16) | (b2 << 8) | (b1 ); 28 | return lt; 29 | } 30 | 31 | void load_sample_locations() { 32 | Serial.print("bank# : bankstart[] samplelen[] "); 33 | Serial.println(); 34 | for (byte i = 0; i < number_of_banks; i++) { 35 | bankstart[i] = (i * sfblocks * 0x10000 * 4); 36 | samplelen[i] = recall_sample_length(i); 37 | if (samplelen[i]>=4294967294){ 38 | samplelen[i]=0; 39 | } 40 | Serial.print(i); 41 | Serial.print(" : "); 42 | Serial.print(bankstart[i]); 43 | Serial.print(" "); 44 | Serial.println(samplelen[i]); 45 | } 46 | } 47 | 48 | 49 | void startRecording(byte sel) { 50 | rec_target = sel; 51 | Serial.print("startRecording address:"); 52 | int16_t rec_count = 0;; 53 | address = (bankstart[rec_target] / 2) + foffset; 54 | Serial.println(address); 55 | queue_left.begin(); 56 | queue_right.begin(); 57 | 58 | 59 | } 60 | 61 | void stopRecording() { 62 | samplelen[rec_target] = ((address) - ((bankstart[rec_target] / 2) + foffset)) / 2; 63 | save_sample_length(rec_target, samplelen[rec_target]); 64 | 65 | Serial.print("stopRecording "); 66 | Serial.print(address); 67 | Serial.print(" "); Serial.println(samplelen[rec_target]); 68 | queue_right.end(); 69 | queue_left.end(); 70 | 71 | while (queue_left.available() > 0) { 72 | queue_left.freeBuffer(); 73 | queue_left.clear(); 74 | queue_right.freeBuffer(); 75 | queue_right.clear(); 76 | } 77 | 78 | } 79 | void continueRecording() { 80 | byte q1a = queue_left.available(); 81 | byte q2a = queue_right.available(); 82 | 83 | 84 | if (q1a == 1 && q2a == 1) { 85 | 86 | int16_t buffer_in_left[(getsize * 4) + 10]; 87 | int16_t buffer_in_right[(getsize * 4) + 10]; 88 | int16_t buffer_out[(getsize * 2) + 10]; 89 | 90 | memcpy(buffer_in_left, queue_left.readBuffer(), getsize); 91 | memcpy(buffer_in_right, queue_right.readBuffer(), getsize); 92 | 93 | for (uint32_t i = 0; i < getsize; i ++) { 94 | uint16_t j = i * 2; 95 | buffer_out[j] = buffer_in_left[i]; 96 | buffer_out[j + 1] = buffer_in_right[i]; 97 | } 98 | 99 | AudioStartUsingSPI(); 100 | SerialFlash.write(address * 2, buffer_out, getsize * 2); 101 | AudioStopUsingSPI(); 102 | 103 | queue_left.freeBuffer(); 104 | queue_right.freeBuffer(); 105 | 106 | address += getsize; 107 | 108 | if (address > ((rec_size * 2) + (bankstart[rec_target]) / 2)) { 109 | Serial.println("max bank size reached "); 110 | stopRecording() ; 111 | } 112 | 113 | } 114 | 115 | } 116 | 117 | void eraseBlocks(int estart, int elen) { 118 | Serial.print("erasing block: "); 119 | Serial.print(estart); 120 | Serial.print(" "); 121 | for (int i = estart; i < estart + elen; i++) { 122 | uint32_t eb = (i * 0x10000); 123 | SerialFlash.eraseBlock(eb); 124 | while (SerialFlash.ready() == false) { 125 | if (millis() - prev[4] > 1000) { 126 | prev[4] = millis(); 127 | Serial.print("."); 128 | } 129 | } 130 | } 131 | Serial.println(" done"); 132 | 133 | } 134 | 135 | void erase_bank(byte bankneum) { 136 | eraseBlocks(sfblocks * bankneum * 4, sfblocks * 4); 137 | } 138 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base_kinda_granular_1/sampler2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * tested on JM's hardware and works 10-16-20 3 | */ 4 | 5 | #include "sampler2.h" 6 | #include "arm_math.h" 7 | #include "utility/dspinst.h" 8 | 9 | 10 | 11 | void AudioSampler::update(void) 12 | { 13 | audio_block_t *ab_left; 14 | audio_block_t *ab_right; 15 | 16 | short *bpl, *bpr, *end; 17 | int32_t val1, val2, val3; 18 | short tempf; 19 | 20 | 21 | if (tone_amp == 0 || playing == 0) return; 22 | ab_left = allocate(); 23 | ab_right = allocate(); 24 | 25 | if (ab_left) { 26 | bpl = ab_left->data; 27 | bpr = ab_right->data; 28 | 29 | 30 | for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { 31 | 32 | if (rev == 0) { 33 | 34 | if (playing == 0) { 35 | *bpl++ = (short)(0); 36 | *bpr++ = (short)(0); 37 | } 38 | 39 | if (playing == 1) { 40 | pindex = index; 41 | index = tone_phase >> 23; //23 is 256 //changing causes rate reduction 42 | //Serial.println(index); 43 | 44 | if (pindex > 128 && index < 128) { //did it wrap around 45 | fpos += 256; // this is fixed its the max size of index 46 | get = 1; 47 | } 48 | 49 | if (fpos + index > sample_len ) { 50 | if (looping == 1) { 51 | fpos = mod_start_pos; 52 | index = 0; 53 | tone_phase = 0; 54 | get = 1; 55 | loop_trig1 = !loop_trig1; 56 | } 57 | if (looping == 0) { 58 | playing = 0; 59 | } 60 | 61 | } 62 | 63 | if (fpos + index > mod_start_pos + end_mod && end_mod_en == 1) { 64 | fpos = mod_start_pos; 65 | index = 0; 66 | tone_phase = 0; 67 | get = 0; 68 | bankshift = 0; 69 | bankoff = 0; 70 | if (looping == 1) { 71 | loop_trig1 = !loop_trig1; 72 | } 73 | if (looping == 0) { 74 | playing = 0; 75 | } 76 | } 77 | 78 | if (get == 1) { 79 | get = 0; 80 | //gfd = micros() - gfcm; 81 | //gfcm = micros(); 82 | uint32_t actualget = start_pos + (fpos * 4); 83 | 84 | //if (SerialFlash.ready() == 1) { //seems to always be ready untill its crashed 85 | AudioStartUsingSPI(); 86 | SerialFlash.read(actualget, in8, buffrl); 87 | AudioStopUsingSPI(); 88 | 89 | 90 | js = 0; 91 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 92 | sample_left_A[js] = (in8[j + 1] << 8) | (in8[j]); 93 | sample_right_A[js] = (in8[j + 3] << 8) | (in8[j + 2]); 94 | js++; 95 | } 96 | 97 | } 98 | 99 | scale = (tone_phase >> 7) & 0xFFFF; 100 | 101 | val1 = *(sample_left_A + index ); 102 | val2 = *(sample_left_A + (index + 1) ); 103 | val2 *= scale; 104 | val1 *= 0xFFFF - scale; 105 | val3 = (val1 + val2) >> 16; 106 | *bpl++ = (short)((val3 * tone_amp) >> 15); 107 | 108 | val1 = *(sample_right_A + index ); 109 | val2 = *(sample_right_A + (index + 1) ); 110 | val2 *= scale; 111 | val1 *= 0xFFFF - scale; 112 | val3 = (val1 + val2) >> 16; 113 | *bpr++ = (short)((val3 * tone_amp) >> 15); 114 | 115 | tone_phase += tone_incr; 116 | tone_phase &= 0x7fffffff; 117 | 118 | 119 | } 120 | } 121 | 122 | 123 | if (rev == 1) { 124 | 125 | 126 | if (playing == 0) { 127 | *bpl++ = (short)(0); 128 | *bpr++ = (short)(0); 129 | } 130 | 131 | if (playing == 1) { 132 | pindex = index; 133 | index = tone_phase >> 23; 134 | revindex = (index - 255) * -1; 135 | bankoff = 0; 136 | 137 | if (pindex > 128 && index < 128) { 138 | fpos -= (256); 139 | 140 | get = 1; 141 | 142 | 143 | } 144 | 145 | if (fpos < 0) { 146 | fpos = sample_len; 147 | index = 0; 148 | tone_phase = 0; 149 | get = 1; 150 | //Serial.println("end"); 151 | if (looping == 0) { 152 | playing = 0; 153 | } 154 | if (looping == 1) { 155 | loop_trig1 = !loop_trig1; 156 | } 157 | 158 | } 159 | 160 | if (get == 1) { 161 | get = 0; 162 | // uint32_t tt = micros(); 163 | uint32_t rev_sactualget = rev_start + (fpos * 4); 164 | //Serial.print("Rag "); 165 | // Serial.println(rev_sactualget); 166 | // if (SerialFlash.ready() == 1) { 167 | AudioStartUsingSPI(); 168 | SerialFlash.read(rev_sactualget, in8, buffrl); 169 | AudioStopUsingSPI(); 170 | 171 | js = 0; 172 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 173 | sample_left_A[js] = (in8[j + 1] << 8) | (in8[j]); 174 | sample_right_A[js] = (in8[j + 3] << 8) | (in8[j + 2]); 175 | js++; 176 | } 177 | 178 | } 179 | 180 | scale = (tone_phase >> 7) & 0xFFFF; 181 | 182 | val1 = *(sample_left_A + revindex + 1 + bankoff); 183 | val2 = *(sample_left_A + (revindex ) + bankoff); 184 | val2 *= scale; 185 | val1 *= 0xFFFF - scale; 186 | val3 = (val1 + val2) >> 16; 187 | *bpl++ = (short)((val3 * tone_amp) >> 15); 188 | 189 | val1 = *(sample_right_A + revindex + 1 + bankoff); 190 | val2 = *(sample_right_A + revindex + bankoff); 191 | val2 *= scale; 192 | val1 *= 0xFFFF - scale; 193 | val3 = (val1 + val2) >> 16; 194 | *bpr++ = (short)((val3 * tone_amp) >> 15); 195 | 196 | tone_phase += tone_incr; 197 | tone_phase &= 0x7fffffff; 198 | 199 | } 200 | } 201 | } 202 | 203 | transmit(ab_left, 0); 204 | transmit(ab_right, 1); 205 | 206 | release(ab_left); 207 | release(ab_right); 208 | 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base_kinda_granular_1/sampler2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tested on JM's hardware and works 10-16-20 3 | */ 4 | 5 | #ifndef synth_sampler_h_ 6 | #define synth_sampler_h_ 7 | 8 | #include "Arduino.h" 9 | #include "AudioStream.h" 10 | #include "arm_math.h" 11 | #include 12 | #include "spi_interrupt.h" 13 | 14 | 15 | #define AUDIO_SAMPLE_RATE_ROUNDED (44118) 16 | 17 | 18 | class AudioSampler : 19 | public AudioStream 20 | { 21 | 22 | public: 23 | AudioSampler(void) : 24 | AudioStream(0, NULL), tone_amp(0), tone_freq(0), 25 | tone_width(0.25), tone_incr(0), 26 | looping(0), playing(0) 27 | { 28 | } 29 | 30 | void frequency(float t_freq) { 31 | t_freq = norm * t_freq; 32 | if (t_freq < 0.0) t_freq = 0.0; 33 | else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) t_freq = AUDIO_SAMPLE_RATE_EXACT / 2; 34 | tone_incr = (t_freq * (0x80000000LL / AUDIO_SAMPLE_RATE_EXACT)) + 0.5; 35 | } 36 | 37 | void amplitude(float n) { // 0 to 1.0 38 | if (n < 0) n = 0; 39 | else if (n > 1.0) n = 1.0; 40 | if ((tone_amp == 0) && n) { 41 | // reset the phase when the amplitude was zero 42 | // and has now been increased. 43 | tone_phase = 0; 44 | } 45 | // set new magnitude 46 | tone_amp = n * 32767.0; 47 | } 48 | 49 | void begin(float t_amp, float t_freq, uint32_t s_pos, uint32_t len) { 50 | amplitude(t_amp); 51 | frequency(t_freq); 52 | sample_len = len; 53 | start_pos = s_pos; 54 | end_mod = len; 55 | mod_start_pos = 0; 56 | get = 0; 57 | } 58 | 59 | void sample_loop(int bb) { 60 | looping = bb; 61 | } 62 | 63 | void sample_play_loc(uint32_t s_pos, uint32_t len) { 64 | 65 | if (rev == 0) { 66 | fpos = 0; 67 | sample_len = len; 68 | start_pos = s_pos; //44 BYTES IN WAVE HEADER 69 | end_mod = len; 70 | index = 0; 71 | tone_phase = 0; 72 | get = 0; 73 | bankshift = 0; 74 | bankoff = 0; 75 | 76 | 77 | AudioStartUsingSPI(); 78 | SerialFlash.read(start_pos + (fpos * 4), in8b, buffrl); 79 | AudioStopUsingSPI(); 80 | 81 | js = 0; 82 | for (uint16_t j = 0; j < buffrl - 4; j += 4) { 83 | int16_t new_left = (in8b[j + 1] << 8) | (in8b[j]); 84 | int16_t new_right = (in8b[j + 3] << 8) | (in8b[j + 2]); 85 | sample_left_A[js] = new_left; 86 | sample_right_A[js] = new_right; 87 | js++; 88 | } 89 | 90 | playing = 1; 91 | 92 | } 93 | 94 | if (rev == 1) { 95 | sample_len = len; 96 | rev_start = s_pos ; 97 | fpos = len; 98 | rev_end = s_pos; 99 | rev_mod_start_pos = rev_start; 100 | index = 0; 101 | tone_phase = 0; 102 | get = 0; 103 | bankshift = 3; 104 | bankoff = bankshift << 8; 105 | // Serial.print("rev_start "); Serial.println(rev_start); 106 | // Serial.print("rev_end "); Serial.println(rev_end); 107 | // Serial.println(); 108 | playing = 1; 109 | 110 | } 111 | 112 | } 113 | 114 | 115 | 116 | void sample_stop() { 117 | playing = 0; 118 | } 119 | 120 | uint16_t sample_status() { 121 | return playing; 122 | } 123 | 124 | void sample_reverse(byte bb) { 125 | rev = bb; 126 | if (rev != prev_rev) { 127 | get = 1; 128 | } 129 | prev_rev = bb; 130 | //fpos = sample_len; 131 | 132 | } 133 | 134 | uint32_t sample_start_pos(float pd) { 135 | mod_start_pos = pd * (sample_len - 256); 136 | return rev_mod_start_pos; 137 | } 138 | 139 | uint32_t sample_play_len(float pd) { 140 | //pd=(pd*-1.00)+1.00; 141 | if (pd > 0) { 142 | end_mod_en = 1; 143 | end_mod = (pd * sample_len) + 256; 144 | } 145 | if (pd == 0) { 146 | end_mod_en = 0; 147 | } 148 | return end_mod; 149 | } 150 | 151 | uint32_t sample_loc(void) { 152 | uint32_t a = (uint32_t)index; 153 | return sample_address + a; 154 | } 155 | 156 | uint32_t revstart() { 157 | return rev_start; 158 | } 159 | 160 | uint32_t revend() { 161 | return rev_end; 162 | } 163 | 164 | byte loop_trig() { 165 | return loop_trig1; 166 | } 167 | 168 | uint32_t transfer_time() { 169 | return gfd; 170 | } 171 | 172 | virtual void update(void); 173 | 174 | private: 175 | #define SPI_SIZE (256) // how many 16b samples in each channel 176 | //2048 35ms single sample 177 | uint32_t gfcm, gfd; 178 | float norm = 86.1679 * 2; //normal playback speed 179 | 180 | short tone_amp; 181 | short tone_freq; 182 | uint32_t tone_phase; 183 | uint32_t index_assume; 184 | int32_t rev_start, rev_end; 185 | uint32_t tone_width; 186 | short sample; 187 | // volatile prevents the compiler optimizing out the frequency function 188 | volatile uint32_t tone_incr; 189 | short tone_type; 190 | const int16_t *arbdata; 191 | //int16_t *sfsample; 192 | //int16_t *sfsample16; 193 | int16_t js; 194 | uint32_t sf_pos; 195 | uint32_t sample_address; 196 | uint32_t sample_len, start_pos, mod_start_pos, end_mod, rev_mod_start_pos; 197 | char in8[(SPI_SIZE * 4) + 8]; 198 | char in8b[(SPI_SIZE * 4) + 8]; 199 | 200 | int16_t sample_left_A[(SPI_SIZE) + 2]; 201 | int16_t sample_right_A[(SPI_SIZE) + 2]; 202 | 203 | uint16_t get, end_flag; 204 | const uint16_t buffrl = (SPI_SIZE * 4) + 8; 205 | uint16_t pindex; 206 | uint32_t index, scale, end_mod_en; 207 | int32_t revindex = 256; 208 | int32_t fpos, blocknum; 209 | uint16_t looping, playing, rev, bankoff; 210 | int16_t bankshift, bankswitch; 211 | byte loop_trig1; 212 | byte prev_rev; 213 | }; 214 | 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /Class-7/serial_flash_sampler_bleep_base_kinda_granular_1/sampler_helpers2.h: -------------------------------------------------------------------------------- 1 | //this block is all sampler stuff and can be left alone 2 | #define getsize AUDIO_BLOCK_SAMPLES*2 3 | uint32_t rec_size = (sfblocks * 0x10000); 4 | int16_t rec_target, foffset, mode_timer_latch, rec_mode, mode, prev_bank_sel; 5 | uint32_t bankstart[number_of_banks]; 6 | uint32_t samplelen[number_of_banks]; 7 | byte bank_status[number_of_banks]; 8 | uint32_t sfaddress, address; 9 | //end 10 | 11 | int32_t prev[12]; 12 | 13 | void save_sample_length(uint16_t slot, uint32_t to_save) { 14 | int16_t startee = slot * 4; 15 | EEPROM.write(startee, to_save >> 24); 16 | EEPROM.write(startee + 1, to_save >> 16); 17 | EEPROM.write(startee + 2, to_save >> 8); 18 | EEPROM.write(startee + 3, to_save & 0xFF); 19 | } 20 | 21 | uint32_t recall_sample_length(uint16_t slot) { 22 | int16_t startee = slot * 4; 23 | byte b4 = EEPROM.read(startee); 24 | byte b3 = EEPROM.read(startee + 1); 25 | byte b2 = EEPROM.read(startee + 2); 26 | byte b1 = EEPROM.read(startee + 3); 27 | uint32_t lt = (b4 << 24) | (b3 << 16) | (b2 << 8) | (b1 ); 28 | return lt; 29 | } 30 | 31 | void load_sample_locations() { 32 | Serial.print("bank# : bankstart[] samplelen[] "); 33 | Serial.println(); 34 | for (byte i = 0; i < number_of_banks; i++) { 35 | bankstart[i] = (i * sfblocks * 0x10000 * 4); 36 | samplelen[i] = recall_sample_length(i); 37 | if (samplelen[i]>=4294967294){ 38 | samplelen[i]=0; 39 | } 40 | Serial.print(i); 41 | Serial.print(" : "); 42 | Serial.print(bankstart[i]); 43 | Serial.print(" "); 44 | Serial.println(samplelen[i]); 45 | } 46 | } 47 | 48 | 49 | void startRecording(byte sel) { 50 | rec_target = sel; 51 | Serial.print("startRecording address:"); 52 | int16_t rec_count = 0;; 53 | address = (bankstart[rec_target] / 2) + foffset; 54 | Serial.println(address); 55 | queue_left.begin(); 56 | queue_right.begin(); 57 | 58 | 59 | } 60 | 61 | void stopRecording() { 62 | samplelen[rec_target] = ((address) - ((bankstart[rec_target] / 2) + foffset)) / 2; 63 | save_sample_length(rec_target, samplelen[rec_target]); 64 | 65 | Serial.print("stopRecording "); 66 | Serial.print(address); 67 | Serial.print(" "); Serial.println(samplelen[rec_target]); 68 | queue_right.end(); 69 | queue_left.end(); 70 | 71 | while (queue_left.available() > 0) { 72 | queue_left.freeBuffer(); 73 | queue_left.clear(); 74 | queue_right.freeBuffer(); 75 | queue_right.clear(); 76 | } 77 | 78 | } 79 | void continueRecording() { 80 | byte q1a = queue_left.available(); 81 | byte q2a = queue_right.available(); 82 | 83 | 84 | if (q1a == 1 && q2a == 1) { 85 | 86 | int16_t buffer_in_left[(getsize * 4) + 10]; 87 | int16_t buffer_in_right[(getsize * 4) + 10]; 88 | int16_t buffer_out[(getsize * 2) + 10]; 89 | 90 | memcpy(buffer_in_left, queue_left.readBuffer(), getsize); 91 | memcpy(buffer_in_right, queue_right.readBuffer(), getsize); 92 | 93 | for (uint32_t i = 0; i < getsize; i ++) { 94 | uint16_t j = i * 2; 95 | buffer_out[j] = buffer_in_left[i]; 96 | buffer_out[j + 1] = buffer_in_right[i]; 97 | } 98 | 99 | AudioStartUsingSPI(); 100 | SerialFlash.write(address * 2, buffer_out, getsize * 2); 101 | AudioStopUsingSPI(); 102 | 103 | queue_left.freeBuffer(); 104 | queue_right.freeBuffer(); 105 | 106 | address += getsize; 107 | 108 | if (address > ((rec_size * 2) + (bankstart[rec_target]) / 2)) { 109 | Serial.println("max bank size reached "); 110 | stopRecording() ; 111 | } 112 | 113 | } 114 | 115 | } 116 | 117 | void eraseBlocks(int estart, int elen) { 118 | Serial.print("erasing block: "); 119 | Serial.print(estart); 120 | Serial.print(" "); 121 | for (int i = estart; i < estart + elen; i++) { 122 | uint32_t eb = (i * 0x10000); 123 | SerialFlash.eraseBlock(eb); 124 | while (SerialFlash.ready() == false) { 125 | if (millis() - prev[4] > 1000) { 126 | prev[4] = millis(); 127 | Serial.print("."); 128 | } 129 | } 130 | } 131 | Serial.println(" done"); 132 | 133 | } 134 | 135 | void erase_bank(byte bankneum) { 136 | eraseBlocks(sfblocks * bankneum * 4, sfblocks * 4); 137 | } 138 | -------------------------------------------------------------------------------- /Class-7/tape_delay_example_for_bleep_base/effect_tape_delay.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "effect_tape_delay.h" 3 | #include "arm_math.h" 4 | #include "utility/dspinst.h" 5 | 6 | void AudioEffectTapeDelay::begin(short *delayline, uint32_t max_len, uint32_t dly_len, short redux, short lerp) 7 | { 8 | max_dly_len = max_len - 1; 9 | 10 | desired_delay_length = dly_len; 11 | if (desired_delay_length > max_dly_len) { 12 | desired_delay_length = max_dly_len; 13 | } 14 | l_delayline = delayline; 15 | write_head = 0; 16 | 17 | rate_redux = redux; 18 | lerp_len = lerp; 19 | } 20 | 21 | void AudioEffectTapeDelay::sampleRate(short redux) 22 | { 23 | rate_redux = redux; 24 | } 25 | 26 | uint32_t AudioEffectTapeDelay::length(uint32_t dly_len) 27 | { 28 | desired_delay_length = dly_len; 29 | if (desired_delay_length > max_dly_len) { 30 | desired_delay_length = max_dly_len; 31 | } 32 | return delay_length; 33 | } 34 | 35 | uint32_t AudioEffectTapeDelay::length_no_lerp(uint32_t dly_len) 36 | { 37 | delay_length = dly_len; 38 | desired_delay_length=dly_len; 39 | if (delay_length > max_dly_len) { 40 | delay_length = max_dly_len; 41 | } 42 | return delay_length; 43 | } 44 | 45 | void AudioEffectTapeDelay::update(void) 46 | { 47 | audio_block_t *block; 48 | short *bp; 49 | //static uint32_t preva; 50 | static short tick, tock; 51 | int input1; 52 | static byte mm; 53 | if (l_delayline == NULL)return; 54 | uint32_t max_dly_len_m = max_dly_len; 55 | block = receiveWritable(0); 56 | if (block) { 57 | bp = block->data; 58 | 59 | for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { 60 | 61 | tick++; 62 | if (tick > lerp_len) { 63 | 64 | if (delay_length < desired_delay_length - 1) { 65 | delay_length++; 66 | } 67 | 68 | if (delay_length > desired_delay_length + 1) { 69 | delay_length--; 70 | } 71 | tick = 0; 72 | } 73 | 74 | 75 | tock++; 76 | if (tock > rate_redux) { 77 | tock = 0; 78 | write_head++; 79 | } 80 | if (write_head >= max_dly_len_m) { 81 | write_head = 0; 82 | } 83 | 84 | read_head = ((write_head) + delay_length); 85 | 86 | if (read_head > (max_dly_len_m - 1)) { 87 | read_head -= (max_dly_len_m); 88 | } 89 | 90 | l_delayline[write_head] = *bp ; 91 | *bp++ = l_delayline[read_head]; 92 | } 93 | 94 | transmit(block); 95 | release(block); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Class-7/tape_delay_example_for_bleep_base/effect_tape_delay.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "AudioStream.h" 3 | #include "arm_math.h" 4 | #include "spi_interrupt.h" 5 | 6 | class AudioEffectTapeDelay : 7 | public AudioStream 8 | { 9 | public: 10 | AudioEffectTapeDelay(void): 11 | AudioStream(1, inputQueueArray) { 12 | } 13 | void begin(short *delayline, uint32_t max_len, uint32_t dly_len, short redux, short lerp); 14 | uint32_t length(uint32_t dly_len); 15 | uint32_t length_no_lerp(uint32_t dly_len); 16 | void sampleRate(short redux); 17 | virtual void update(void); 18 | 19 | private: 20 | uint32_t dlyd, dlyt; 21 | audio_block_t *inputQueueArray[1]; 22 | short *l_delayline; 23 | uint32_t delay_length, desired_delay_length; 24 | int32_t inv_delay_length; 25 | uint32_t max_dly_len; 26 | uint32_t write_head; 27 | uint32_t delay_depth; 28 | uint32_t rate_redux; 29 | uint32_t delay_offset_idx; 30 | uint32_t delay_rate_incr; 31 | uint32_t read_head, feedback; 32 | short SIMPLE_SMOOTH, lerp_len; 33 | uint32_t l_delay_rate_index; 34 | 35 | short sync_out_latch; 36 | short sync_out_count; 37 | }; 38 | -------------------------------------------------------------------------------- /Class-7/tape_delay_example_for_bleep_base/tape_delay_example_for_bleep_base.ino: -------------------------------------------------------------------------------- 1 | // the stadard delay can't have the length cahnged without pops and clicks 2 | // this one works like a stadard tape delay 3 | 4 | #include "effect_tape_delay.h" // this needs to be before the other audio code 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // GUItool: begin automatically generated code 13 | AudioInputI2S i2s2; //xy=82,298 14 | AudioAmplifier amp1; //xy=224,294 15 | AudioMixer4 mixer1; //xy=321,424 16 | AudioEffectTapeDelay delay1; //xy=463,419 17 | AudioMixer4 mixer2; //xy=623,345 18 | AudioOutputI2S i2s1; //xy=804,440 19 | AudioConnection patchCord1(i2s2, 0, amp1, 0); 20 | AudioConnection patchCord2(amp1, 0, mixer1, 0); 21 | AudioConnection patchCord3(amp1, 0, mixer2, 0); 22 | AudioConnection patchCord4(mixer1, delay1); 23 | AudioConnection patchCord5(delay1, 0, mixer2, 1); 24 | AudioConnection patchCord6(delay1, 0, mixer1, 1); 25 | AudioConnection patchCord7(mixer2, 0, i2s1, 0); 26 | AudioConnection patchCord8(mixer2, 0, i2s1, 1); 27 | AudioControlSGTL5000 sgtl5000_1; //xy=575,188 28 | // GUItool: end automatically generated code 29 | 30 | 31 | 32 | //since tape delay isnt in the tool it wont see it 33 | //but you can alwasy use the standard delay module in the tool then swap the name out in here for AudioEffectTapeDelay 34 | 35 | //Some effects require memory to be allocated outside of the AudioMemory() function/ 36 | // At 44.1 kHz sample rate every 500 integers, 1k byte of memory is 11.3 milliseconds 37 | // On the 4.0 there is 1024k bytes of ram 38 | #define DELAY_SIZE 20000 //size in 2xintegers 39 | int16_t tape_delay_bank[DELAY_SIZE]; //int16_t is a more specific way of saying integer 40 | 41 | #include "bleep_base.h" //Then we can add this line that we will still need 42 | 43 | //then you can declare any variables you want. 44 | unsigned long current_time; 45 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 46 | float input_volume, feedback_level, wet_level, dry_level; 47 | long delay_time_adjust; 48 | 49 | 50 | void setup() { 51 | start_bleep_base(); //run this first in setup 52 | 53 | //the delay is outside audio memory as we decalerd the array for it above 54 | AudioMemory(10); 55 | 56 | sgtl5000_1.enable(); //Turn the adapter board on 57 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 58 | sgtl5000_1.lineInLevel(12); //The volume of the input. 0-15 with 15 bing more amplifications 59 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 60 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 61 | 62 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 63 | // For headphones it's pretty loud at .4 64 | sgtl5000_1.volume(0.25); 65 | 66 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 67 | // If you're not using the line out don't worry about it. 68 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 69 | 70 | //begin(bank to store data in(integer array), size of that bank (integer), delay length(integer), reduction(integer), interpolation(integer)) 71 | //bank, and size are all defines above, you jsut need to plug them in 72 | //The bank jsut defines the max size of the delay effect. you can cahge the length here or jsut with "delay1.length()" 73 | //reduction can make the delay longer at the expense of sample rate. 0 is no reduction 1 doubles the leght but halves the sample rate to 22lHz, 2 is 11k and so on. On the 4.0 we've got a lot of memory so 0 i fine but 1 can have it's uses. 74 | //interpolation. how fast does does the tape head move to meet the desided length. Larger numbers mean it takes longer to zip to the new length. This is in integers 75 | //this is a lot but its jsut copy paste really! 76 | delay1.begin(tape_delay_bank, DELAY_SIZE, DELAY_SIZE / 2, 0, 2); 77 | 78 | mixer1.gain(0, 1); //level from input going into delay. we'll adjsut the other levels in the loop 79 | 80 | 81 | } //setup is over 82 | 83 | 84 | void loop() { 85 | update_controls(); 86 | current_time = millis(); 87 | 88 | if (current_time - prev_time[1] > 5) { //we don't need to do all this screamingly fast. Is we slow it down a little there will be less jiggle in the pot readings 89 | prev_time[1] = current_time; 90 | 91 | input_volume = (1.0 - potRead(0)) * 2.0; //we can amplify or attenuate the signal 92 | amp1.gain(input_volume); 93 | 94 | feedback_level = (1.0 - potRead(1)); 95 | mixer1.gain(1, feedback_level); //how much of the delay output comes back into the input mixer 96 | 97 | dry_level = potRead(2); 98 | wet_level = 1.0 - dry_level; //as one goes up the other goes down to control the wet dry mix. 99 | mixer2.gain(0, dry_level); // signal straigh from input 100 | mixer2.gain(1, wet_level); //signal from delay output 101 | 102 | delay_time_adjust = potRead(3) * DELAY_SIZE; //delay size is the max so jsut multiply it bu the 0-1.0 pot 103 | delay1.length(delay_time_adjust); 104 | 105 | } 106 | 107 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 108 | if (current_time - prev_time[0] > 500) { 109 | prev_time[0] = current_time; 110 | Serial.println(feedback_level); 111 | Serial.println(); 112 | 113 | //Here we print out the usage of the audio library 114 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 115 | // If you're using too many block, jut increas the number up top untill you're over it by a few 116 | Serial.print("processor: "); 117 | Serial.print(AudioProcessorUsageMax()); 118 | Serial.print("% Memory: "); 119 | Serial.print(AudioMemoryUsageMax()); 120 | Serial.println(); 121 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 122 | AudioMemoryUsageMaxReset(); 123 | } 124 | 125 | }// loop is over 126 | -------------------------------------------------------------------------------- /Class-8/bleep_base_drone_2/effect_tape_delay.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "effect_tape_delay.h" 3 | #include "arm_math.h" 4 | #include "utility/dspinst.h" 5 | 6 | void AudioEffectTapeDelay::begin(short *delayline, uint32_t max_len, uint32_t dly_len, short redux, short lerp) 7 | { 8 | max_dly_len = max_len - 1; 9 | 10 | desired_delay_length = dly_len; 11 | if (desired_delay_length > max_dly_len) { 12 | desired_delay_length = max_dly_len; 13 | } 14 | l_delayline = delayline; 15 | write_head = 0; 16 | 17 | rate_redux = redux; 18 | lerp_len = lerp; 19 | } 20 | 21 | void AudioEffectTapeDelay::sampleRate(short redux) 22 | { 23 | rate_redux = redux; 24 | } 25 | 26 | uint32_t AudioEffectTapeDelay::length(uint32_t dly_len) 27 | { 28 | desired_delay_length = dly_len; 29 | if (desired_delay_length > max_dly_len) { 30 | desired_delay_length = max_dly_len; 31 | } 32 | return delay_length; 33 | } 34 | 35 | uint32_t AudioEffectTapeDelay::length_no_lerp(uint32_t dly_len) 36 | { 37 | delay_length = dly_len; 38 | desired_delay_length=dly_len; 39 | if (delay_length > max_dly_len) { 40 | delay_length = max_dly_len; 41 | } 42 | return delay_length; 43 | } 44 | 45 | void AudioEffectTapeDelay::update(void) 46 | { 47 | audio_block_t *block; 48 | short *bp; 49 | //static uint32_t preva; 50 | static short tick, tock; 51 | int input1; 52 | static byte mm; 53 | if (l_delayline == NULL)return; 54 | uint32_t max_dly_len_m = max_dly_len; 55 | block = receiveWritable(0); 56 | if (block) { 57 | bp = block->data; 58 | 59 | for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { 60 | 61 | tick++; 62 | if (tick > lerp_len) { 63 | 64 | if (delay_length < desired_delay_length - 1) { 65 | delay_length++; 66 | } 67 | 68 | if (delay_length > desired_delay_length + 1) { 69 | delay_length--; 70 | } 71 | tick = 0; 72 | } 73 | 74 | 75 | tock++; 76 | if (tock > rate_redux) { 77 | tock = 0; 78 | write_head++; 79 | } 80 | if (write_head >= max_dly_len_m) { 81 | write_head = 0; 82 | } 83 | 84 | read_head = ((write_head) + delay_length); 85 | 86 | if (read_head > (max_dly_len_m - 1)) { 87 | read_head -= (max_dly_len_m); 88 | } 89 | 90 | l_delayline[write_head] = *bp ; 91 | *bp++ = l_delayline[read_head]; 92 | } 93 | 94 | transmit(block); 95 | release(block); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Class-8/bleep_base_drone_2/effect_tape_delay.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "AudioStream.h" 3 | #include "arm_math.h" 4 | #include "spi_interrupt.h" 5 | 6 | class AudioEffectTapeDelay : 7 | public AudioStream 8 | { 9 | public: 10 | AudioEffectTapeDelay(void): 11 | AudioStream(1, inputQueueArray) { 12 | } 13 | void begin(short *delayline, uint32_t max_len, uint32_t dly_len, short redux, short lerp); 14 | uint32_t length(uint32_t dly_len); 15 | uint32_t length_no_lerp(uint32_t dly_len); 16 | void sampleRate(short redux); 17 | virtual void update(void); 18 | 19 | private: 20 | uint32_t dlyd, dlyt; 21 | audio_block_t *inputQueueArray[1]; 22 | short *l_delayline; 23 | uint32_t delay_length, desired_delay_length; 24 | int32_t inv_delay_length; 25 | uint32_t max_dly_len; 26 | uint32_t write_head; 27 | uint32_t delay_depth; 28 | uint32_t rate_redux; 29 | uint32_t delay_offset_idx; 30 | uint32_t delay_rate_incr; 31 | uint32_t read_head, feedback; 32 | short SIMPLE_SMOOTH, lerp_len; 33 | uint32_t l_delay_rate_index; 34 | 35 | short sync_out_latch; 36 | short sync_out_count; 37 | }; 38 | -------------------------------------------------------------------------------- /Class-8/bleep_base_drum_machine_1/mem_sampler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * tested on JM's hardware and works 10-16-20 3 | */ 4 | 5 | #include "mem_sampler.h" 6 | #include "arm_math.h" 7 | #include "utility/dspinst.h" 8 | 9 | 10 | 11 | void MemSampler::update(void) 12 | { 13 | audio_block_t *ab_left; 14 | audio_block_t *ab_right; 15 | 16 | 17 | if (playing == 0) return; 18 | ab_left = allocate(); 19 | ab_right = allocate(); 20 | 21 | if (ab_left) { 22 | 23 | for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { 24 | 25 | if (playing == 0) { 26 | ab_left->data[i] = 0; 27 | ab_right->data[i] = 0; 28 | } 29 | 30 | if (playing == 1) { 31 | 32 | prev_index1 = index1; 33 | index1 = accumulator >> (32 - 8); 34 | 35 | if (prev_index1 > 128 && index1 < 128) { 36 | index2 += 255; 37 | } 38 | 39 | if (index2 + index1 >= end_mod) { 40 | index2 = start_pos; 41 | if (looping == 0) { 42 | playing = 0; 43 | } 44 | 45 | } 46 | uint32_t loc = index2 + index1; 47 | if (rev == 1) { 48 | loc = (sample_len - loc); 49 | } 50 | 51 | ab_left->data[i] = sampleMemory[loc]; 52 | ab_right->data[i] = sampleMemory[loc]; 53 | accumulator += increment; 54 | } 55 | 56 | 57 | 58 | } 59 | 60 | transmit(ab_left, 0); 61 | transmit(ab_right, 1); 62 | 63 | release(ab_left); 64 | release(ab_right); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Class-8/bleep_base_drum_machine_1/mem_sampler.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef synth_MemSampler_h_ 3 | #define synth_MemSampler_h_ 4 | 5 | #include "Arduino.h" 6 | #include "AudioStream.h" 7 | #include "arm_math.h" 8 | 9 | #define AUDIO_SAMPLE_RATE_ROUNDED (44118) 10 | 11 | 12 | class MemSampler : 13 | public AudioStream 14 | { 15 | 16 | public: 17 | MemSampler(void) : 18 | AudioStream(0, NULL) { 19 | } 20 | 21 | void frequency(float t_freq) { 22 | t_freq = norm * t_freq; 23 | if (t_freq < 0.0) t_freq = 0.0; 24 | else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) t_freq = AUDIO_SAMPLE_RATE_EXACT / 2; 25 | increment = (t_freq * (0x80000000LL / AUDIO_SAMPLE_RATE_EXACT)) + 0.5; 26 | } 27 | 28 | 29 | void begin(unsigned int *in_sample, uint32_t len) { 30 | frequency(norm); 31 | sampleMemory = in_sample; 32 | sample_len = len; 33 | start_pos = 0; 34 | end_mod = len; 35 | } 36 | 37 | void start_location(uint32_t starts) { 38 | start_pos = starts; 39 | if (start_pos >= sample_len) { 40 | start_pos = sample_len - 255; 41 | } 42 | } 43 | 44 | void play_length(uint32_t plength) { 45 | end_mod=start_pos+plength; 46 | if (end_mod >= sample_len) { 47 | end_mod = sample_len; 48 | } 49 | } 50 | 51 | void sample_loop(int bb) { 52 | looping = bb; 53 | } 54 | 55 | void play() { 56 | index2 = start_pos; 57 | index1 = 0; 58 | playing = 1; 59 | } 60 | 61 | void stop() { 62 | playing = 0; 63 | } 64 | 65 | void sample_reverse(byte bb) { 66 | rev = bb; 67 | } 68 | 69 | virtual void update(void); 70 | 71 | private: 72 | // volatile prevents the compiler optimizing out the frequency function 73 | volatile uint32_t increment; 74 | uint32_t accumulator; 75 | float norm = 86.1679 * 2; //normal playback speed 76 | unsigned int *sampleMemory; 77 | short tone_freq; 78 | int32_t rev_start, rev_end; 79 | 80 | short tone_type; 81 | int16_t js; 82 | uint32_t sf_pos; 83 | uint32_t sample_address; 84 | uint32_t sample_len, start_pos, mod_start_pos, end_mod, rev_mod_start_pos; 85 | uint32_t index1, index2, prev_index1, scale, end_mod_en; 86 | int32_t fpos, blocknum; 87 | uint16_t looping, playing, rev, bankoff; 88 | int16_t bankshift, bankswitch; 89 | uint32_t print_count; 90 | byte loop_trig1; 91 | byte prev_rev; 92 | }; 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dadageek-Feb21 2 | Code and notes for "Making Synths with Arduino" 3 | 4 | ## See the [wiki](https://github.com/BleepLabs/dadageek-Feb21/wiki) for all the notes and info 5 | -------------------------------------------------------------------------------- /docs/Bleep base v1.dch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/Bleep base v1.dch -------------------------------------------------------------------------------- /docs/Bleep base v1.dip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/Bleep base v1.dip -------------------------------------------------------------------------------- /docs/Bleep-base-v1-schematic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/Bleep-base-v1-schematic.jpg -------------------------------------------------------------------------------- /docs/Class 1 notes - Basic hardware.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/Class 1 notes - Basic hardware.pdf -------------------------------------------------------------------------------- /docs/audio-adapter-dc-couple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/audio-adapter-dc-couple.png -------------------------------------------------------------------------------- /docs/audio_array.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/audio_array.jpg -------------------------------------------------------------------------------- /docs/bleep_base_header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/bleep_base_header.jpg -------------------------------------------------------------------------------- /docs/bleepbase_overhead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/bleepbase_overhead.png -------------------------------------------------------------------------------- /docs/example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/example-1.png -------------------------------------------------------------------------------- /docs/flashchip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/flashchip.jpg -------------------------------------------------------------------------------- /docs/sample_tab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/sample_tab.jpg -------------------------------------------------------------------------------- /docs/uno-and-teensy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/uno-and-teensy.png -------------------------------------------------------------------------------- /docs/wav2sketch-browser.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BleepLabs/dadageek-Feb21/386f8c5c10dc9e32bb39fe438169f094fc1f2ba8/docs/wav2sketch-browser.jpg -------------------------------------------------------------------------------- /extras/granular_example/granular_example.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioInputI2S i2s2; //xy=215,409 17 | AudioEffectGranular granular1; //xy=432,403 18 | AudioMixer4 mixer1; //xy=648,421 19 | AudioOutputI2S i2s1; //xy=809,360 20 | AudioConnection patchCord1(i2s2, 0, granular1, 0); 21 | AudioConnection patchCord2(granular1, 0, mixer1, 0); 22 | AudioConnection patchCord3(mixer1, 0, i2s1, 0); 23 | AudioConnection patchCord4(mixer1, 0, i2s1, 1); 24 | AudioControlSGTL5000 sgtl5000_1; //xy=631,559 25 | // GUItool: end automatically generated code 26 | 27 | 28 | #include "bleep_base.h" //Then we can add this line that we will still need 29 | 30 | //then you can declare any variables you want. 31 | unsigned long current_time; 32 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 33 | 34 | #define GRANULAR_MEMORY_SIZE 12800 // enough for 290 ms at 44.1 kHz 35 | int16_t granularMemory[GRANULAR_MEMORY_SIZE]; 36 | 37 | 38 | void setup() { 39 | start_bleep_base(); //run this first in setup 40 | 41 | //there's a lot we need to do in setup now but most of it is just copy paste. 42 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 43 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 44 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 45 | // It's usually the delay and reverb that hog it. 46 | AudioMemory(10); 47 | 48 | sgtl5000_1.enable(); //Turn the adapter board on 49 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 50 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 51 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 52 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 53 | 54 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 55 | // For headphones it's pretty loud at .4 56 | // There are lots of places we can change the final volume level. 57 | // For now lets set this one once and leave it alone. 58 | sgtl5000_1.volume(0.25); 59 | 60 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 61 | // If you're not using the line out don't worry about it. 62 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 63 | 64 | 65 | granular1.begin(granularMemory, GRANULAR_MEMORY_SIZE); 66 | 67 | mixer1.gain(0, 1); 68 | mixer1.gain(1, 0); 69 | mixer1.gain(2, 0); 70 | mixer1.gain(3, 0); 71 | 72 | } //setup is over 73 | 74 | void loop() { 75 | update_controls(); 76 | current_time = millis(); 77 | 78 | if (buttonState(0) == FELL) { 79 | float msec = potRead(0) * 200.0; 80 | granular1.beginFreeze(msec); 81 | } 82 | if (buttonState(0) == ROSE) { 83 | granular1.stop(); 84 | } 85 | 86 | if (buttonState(1) == FELL) { 87 | float msec = potRead(0) * 200.0; 88 | granular1.beginPitchShift(msec); 89 | } 90 | if (buttonState(1) == ROSE) { 91 | granular1.stop(); 92 | } 93 | 94 | granular1.setSpeed(potRead(1) * 4.0); 95 | 96 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 97 | if (current_time - prev_time[0] > 500) { 98 | prev_time[0] = current_time; 99 | 100 | //Here we print out the usage of the audio library 101 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 102 | // If you're using too many block, jut increas the number up top untill you're over it by a few 103 | Serial.print("processor: "); 104 | Serial.print(AudioProcessorUsageMax()); 105 | Serial.print("% Memory: "); 106 | Serial.print(AudioMemoryUsageMax()); 107 | Serial.println(); 108 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 109 | AudioMemoryUsageMaxReset(); 110 | } 111 | 112 | }// loop is over 113 | -------------------------------------------------------------------------------- /extras/granular_example_with_vca_mod/granular_example_with_vca_mod.ino: -------------------------------------------------------------------------------- 1 | // The block we copied from the tool is pasted below 2 | // design tool: https://www.pjrc.com/teensy/gui/ 3 | 4 | // "#include" means add another file to our code 5 | // So far we've been copy and pasting things in but we can just tell our code to look 6 | // in a library for more functions and data 7 | // These are all necessary to get audio working but we don't need to do anything besides include them 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // GUItool: begin automatically generated code 16 | AudioSynthWaveform waveform1; //xy=118,571 17 | AudioSynthWaveformDc dc1; //xy=120,637 18 | AudioInputI2S i2s2; //xy=215,409 19 | AudioMixer4 mixer2; //xy=272,608 20 | AudioEffectMultiply multiply1; //xy=374,501 21 | AudioEffectGranular granular1; //xy=432,403 22 | AudioMixer4 mixer1; //xy=648,421 23 | AudioOutputI2S i2s1; //xy=809,360 24 | AudioConnection patchCord1(waveform1, 0, mixer2, 0); 25 | AudioConnection patchCord2(dc1, 0, mixer2, 1); 26 | AudioConnection patchCord3(i2s2, 0, granular1, 0); 27 | AudioConnection patchCord4(i2s2, 0, multiply1, 0); 28 | AudioConnection patchCord5(mixer2, 0, multiply1, 1); 29 | AudioConnection patchCord6(multiply1, 0, mixer1, 1); 30 | AudioConnection patchCord7(granular1, 0, mixer1, 0); 31 | AudioConnection patchCord8(mixer1, 0, i2s1, 0); 32 | AudioConnection patchCord9(mixer1, 0, i2s1, 1); 33 | AudioControlSGTL5000 sgtl5000_1; //xy=631,559 34 | // GUItool: end automatically generated code 35 | 36 | 37 | 38 | #include "bleep_base.h" //Then we can add this line that we will still need 39 | 40 | //then you can declare any variables you want. 41 | unsigned long current_time; 42 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 43 | 44 | #define GRANULAR_MEMORY_SIZE 12800 // enough for 290 ms at 44.1 kHz 45 | int16_t granularMemory[GRANULAR_MEMORY_SIZE]; 46 | 47 | 48 | void setup() { 49 | start_bleep_base(); //run this first in setup 50 | 51 | //there's a lot we need to do in setup now but most of it is just copy paste. 52 | // This first group should only be done in setup how much RAM to set aside for the audio library to use. 53 | // The audio library uses blocks of a set size so this is not a percentage or kilobytes, just a kind of arbitrary number. 54 | // On our Teensy 4.0 we can go up to almost 2000 but that won't leave any RAM for anyone else. 55 | // It's usually the delay and reverb that hog it. 56 | AudioMemory(10); 57 | 58 | sgtl5000_1.enable(); //Turn the adapter board on 59 | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); //Tell it what input we want to use. Not necessary is you're not using the ins 60 | sgtl5000_1.lineInLevel(10); //The volume of the input. 0-15 with 15 bing more amplifications 61 | //sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); 62 | //sgtl5000_1.micGain(13); //0 - 63bd of gain. 63 | 64 | //headphone jack output volume. Goes from 0.0 to 1.0 but a 100% signal will clip over .8 or so. 65 | // For headphones it's pretty loud at .4 66 | // There are lots of places we can change the final volume level. 67 | // For now lets set this one once and leave it alone. 68 | sgtl5000_1.volume(0.25); 69 | 70 | //The line out has a seperate level control but it's not meant to be adjusted like the volume function above. 71 | // If you're not using the line out don't worry about it. 72 | sgtl5000_1.lineOutLevel(21); //11-32, the smaller the louder. 21 is about 2 Volts peak to peak 73 | 74 | waveform1.begin(1, 400, WAVEFORM_SQUARE); 75 | mixer2.gain(0, .5); 76 | mixer2.gain(1, 1); 77 | 78 | dc1.amplitude(.5); 79 | 80 | granular1.begin(granularMemory, GRANULAR_MEMORY_SIZE); 81 | 82 | mixer1.gain(0, 0); 83 | mixer1.gain(1, 1); 84 | mixer1.gain(2, 0); 85 | mixer1.gain(3, 0); 86 | 87 | } //setup is over 88 | 89 | void loop() { 90 | update_controls(); 91 | current_time = millis(); 92 | 93 | if (buttonState(0) == FELL) { 94 | float msec = potRead(0) * 200.0; 95 | granular1.beginFreeze(msec); 96 | } 97 | if (buttonState(0) == ROSE) { 98 | granular1.stop(); 99 | } 100 | 101 | if (buttonState(1) == FELL) { // 102 | float msec = potRead(0) * 200.0; 103 | granular1.beginPitchShift(msec); 104 | } 105 | if (buttonState(1) == ROSE) { 106 | granular1.stop(); 107 | } 108 | 109 | granular1.setSpeed(potRead(1) * 4.0); 110 | 111 | //We don't have to do anything in the loop since the audio library will jut keep doing what we told it in the setup 112 | if (current_time - prev_time[0] > 500) { 113 | prev_time[0] = current_time; 114 | 115 | //Here we print out the usage of the audio library 116 | // If we go over 90% processor usage or get near the value of memory blocks we set aside in the setup we'll have issues or crash. 117 | // If you're using too many block, jut increas the number up top untill you're over it by a few 118 | Serial.print("processor: "); 119 | Serial.print(AudioProcessorUsageMax()); 120 | Serial.print("% Memory: "); 121 | Serial.print(AudioMemoryUsageMax()); 122 | Serial.println(); 123 | AudioProcessorUsageMaxReset(); //We need to reset these values so we get a real idea of what the audio code is doing rather than just peaking in every half a second 124 | AudioMemoryUsageMaxReset(); 125 | } 126 | 127 | }// loop is over 128 | -------------------------------------------------------------------------------- /extras/photocell_calibrate_example/photocell_calibrate_example.ino: -------------------------------------------------------------------------------- 1 | //Hold a button to calibrate the photocell to a range and then cahnge it's resposne to logarithmic 2 | //Based on Stefano's idea 3 | 4 | #include "bleep_base.h" 5 | unsigned long current_time; 6 | unsigned long prev_time[8]; //an array of 8 variables all named "prev_time" 7 | int calibrate_mode = 2; //start it at someting other than 0 or 1 so it won't print untill after you calibrate 8 | int maxRead; 9 | int minRead; 10 | float sensorOut; 11 | 12 | void setup() { 13 | start_bleep_base(); //run this first in setup 14 | } //setup is over 15 | 16 | void loop() { 17 | update_controls(); //run this first in the loop 18 | current_time = millis(); //then check the time 19 | 20 | if (buttonState(0) == ROSE) { 21 | calibrate_mode = 0; 22 | Serial.println("...End of Calibration"); 23 | Serial.print(minRead); 24 | Serial.print(" "); 25 | Serial.println(maxRead); 26 | } 27 | 28 | if (buttonState(0) == FELL) { 29 | calibrate_mode = 1; 30 | maxRead = 2; //these should only happen once when the calibration begins 31 | minRead = 1; 32 | Serial.println("Calibrating ..."); 33 | 34 | } 35 | if (calibrate_mode == 1) { 36 | //maxRead = 2; //if these are here they will continue to set max and minRead to 2 and 1 37 | //minRead = 1; 38 | //update_controls(); //not needed for analogRead 39 | 40 | //do the calibration 41 | //this is all good! 42 | int currentRead = analogRead(A2); 43 | if (currentRead > maxRead) 44 | { 45 | maxRead = currentRead; 46 | } 47 | if (currentRead < minRead) 48 | { 49 | minRead = currentRead; 50 | } 51 | } 52 | 53 | float sensorSteps = 200; 54 | //I think i get where you're going with the log and its a good idea but fscale will work better 55 | //sensor steps is a good idea 56 | // fscale is very similar to map but you can appy an arbitrary curve to it. -1.0 is a very log respose while 1.0 is very exonential. 1.0 is linear 57 | 58 | //sensorOut = map(log(analogRead(A2)), log(minRead), log(maxRead), 0, int(sensorSteps)) / sensorSteps ; 59 | sensorOut = fscale(analogRead(A2), -.8, minRead, maxRead, 0, sensorSteps) / sensorSteps; 60 | 61 | if (current_time - prev_time[0] > 20 && calibrate_mode == 0) { //don't print when calibrating 62 | prev_time[0] = current_time; 63 | Serial.println(sensorOut); 64 | } 65 | 66 | }// loop is over 67 | 68 | 69 | //from here with a few little cahnges https://playground.arduino.cc/Main/Fscale/ 70 | float fscale(float inputValue, float curve, float originalMin, float originalMax, float newBegin, float newEnd) { 71 | 72 | float OriginalRange = 0; 73 | float NewRange = 0; 74 | float zeroRefCurVal = 0; 75 | float normalizedCurVal = 0; 76 | float rangedValue = 0; 77 | boolean invFlag = 0; 78 | 79 | 80 | // condition curve parameter 81 | // limit range 82 | 83 | if (curve > 1) curve = 1; 84 | if (curve < -1) curve = -1; 85 | 86 | curve = (curve * -1.0) ; 87 | curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function 88 | 89 | // Check for out of range inputValues 90 | if (inputValue < originalMin) { 91 | inputValue = originalMin; 92 | } 93 | if (inputValue > originalMax) { 94 | inputValue = originalMax; 95 | } 96 | 97 | // Zero Refference the values 98 | OriginalRange = originalMax - originalMin; 99 | 100 | if (newEnd > newBegin) { 101 | NewRange = newEnd - newBegin; 102 | } 103 | else 104 | { 105 | NewRange = newBegin - newEnd; 106 | invFlag = 1; 107 | } 108 | 109 | zeroRefCurVal = inputValue - originalMin; 110 | normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float 111 | 112 | // Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine 113 | if (originalMin > originalMax ) { 114 | return 0; 115 | } 116 | 117 | if (invFlag == 0) { 118 | rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin; 119 | 120 | } 121 | else // invert the ranges 122 | { 123 | rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange); 124 | } 125 | 126 | return rangedValue; 127 | } 128 | --------------------------------------------------------------------------------