Auduino. Sintetizador granular basado en Arduino

  • 1
#1 por Man with the x-ray eyes el 20/01/2013
Hola a todos,
hoy os presento un proyecto muy sencillo y que da bastante juego. Es el primer proyecto que hice con arduino y el que me incitó a seguir haciendo más cosas.
En la web podéis encontrar mucha información y modificaciones. El que aquí os presento es el que he hecho este fin de semana para regalárselo a un amigo por su cumple...
He usado la caja de un router viejo para meter los componentes.
Ahí va:

INGREDIENTES

1 arduino Uno. ¡Cuidado! dependiendo del Arduino que se use el código puede no ser válido, ya que tienen distintos chips. P.ej. no es
compatible con Arduino Leonardo (comprobado XD).
5 potenciómetros de 5k
1 altavoz
1 conector hembra de minijack
1 led conectado al pin13 y a "ground" del arduino.(no viene en el esquema)
5 perillas para los potenciómetros. No son fáciles de encontrar en España así que las compré en Spiratronics
Cable, estaño, soldador, taladro
1 caja de un router viejo o similar. El router ha sido bastante fácil usarlo ya que el plástico es muy fácil de taladrar y se pueden aprovechar
algunos de los agujeros que tiene para el conector de corriente o el USB del Arduino .

CÓDIGO ¡¡¡IMPORTANTE!!! viendo la vista previa aparece varias veces un emoticono en el código eso es un "8" y un ")" que van juntos.

// Auduino, the Lo-Fi granular synthesiser
//
// by Peter Knight, Tinker.it http://tinker.it
//
// Help: http://code.google.com/p/tinkerit/wiki/Auduino
// More help: http://groups.google.com/group/auduino
//
// Analog in 0: Grain 1 pitch
// Analog in 1: Grain 2 decay
// Analog in 2: Grain 1 decay
// Analog in 3: Grain 2 pitch
// Analog in 4: Grain repetition frequency
//
// Digital 3: Audio out (Digital 11 on ATmega8)
//
// Changelog:
// 19 Nov 2008: Added support for ATmega8 boards
// 21 Mar 2009: Added support for ATmega328 boards
// 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
// 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)

#include <avr/io.h>
#include <avr/interrupt.h>

uint16_t syncPhaseAcc;
uint16_t syncPhaseInc;
uint16_t grainPhaseAcc;
uint16_t grainPhaseInc;
uint16_t grainAmp;
uint8_t grainDecay;
uint16_t grain2PhaseAcc;
uint16_t grain2PhaseInc;
uint16_t grain2Amp;
uint8_t grain2Decay;

// Map Analogue channels
#define SYNC_CONTROL (4)
#define GRAIN_FREQ_CONTROL (0)
#define GRAIN_DECAY_CONTROL (2)
#define GRAIN2_FREQ_CONTROL (3)
#define GRAIN2_DECAY_CONTROL (1)


// Changing these will also requires rewriting audioOn()

#if defined(__AVR_ATmega8__)
//
// On old ATmega8 boards.
// Output is on pin 11
//
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 5
#define PWM_PIN 11
#define PWM_VALUE OCR2
#define PWM_INTERRUPT TIMER2_OVF_vect
#elif defined(__AVR_ATmega1280__)
//
// On the Arduino Mega
// Output is on pin 3
//
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 7
#define PWM_PIN 3
#define PWM_VALUE OCR3C
#define PWM_INTERRUPT TIMER3_OVF_vect
#else
//
// For modern ATmega168 and ATmega328 boards
// Output is on pin 3
//
#define PWM_PIN 3
#define PWM_VALUE OCR2B
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 5
#define PWM_INTERRUPT TIMER2_OVF_vect
#endif

// Smooth logarithmic mapping
//
uint16_t antilogTable[] = { 64830,64132,63441,62757,62081,61413,60751,60097,59449,58809,58176,57549,56929,56316,55709,55109,
54515,53928,53347,52773,52204,51642,51085,50535,49991,49452,48920,48393,47871,47356,46846,46341,
45842,45348,44859,44376,43898,43425,42958,42495,42037,41584,41136,40693,40255,39821,39392,38968,
38548,38133,37722,37316,36914,36516,36123,35734,35349,34968,34591,34219,33850,33486,33125,32768
};
uint16_t mapPhaseInc(uint16_t input) {
return (antilogTable[input & 0x3f]) >> (input >> 6);
}

// Stepped chromatic mapping
//
uint16_t midiTable[] = {
17,18,19,20,22,23,24,26,27,29,31,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,
77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,
244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,
732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,
1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,
4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,
10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
22121,23436,24830,26306
};
uint16_t mapMidi(uint16_t input) {
return (midiTable[(1023-input) >> 3]);
}

// Stepped Pentatonic mapping
//
uint16_t pentatonicTable[54] = {
0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,
411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,
3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
};

uint16_t mapPentatonic(uint16_t input) {
uint8_t value = (1023-input) / (1024/53);
return (pentatonicTable[value]);
}


void audioOn() {
#if defined(__AVR_ATmega8__)
// ATmega8 has different registers
TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
TIMSK = _BV(TOIE2);
#elif defined(__AVR_ATmega1280__)
TCCR3A = _BV(COM3C1) | _BV(WGM30);
TCCR3B = _BV(CS30);
TIMSK3 = _BV(TOIE3);
#else
// Set up PWM to 31.25kHz, phase accurate
TCCR2A = _BV(COM2B1) | _BV(WGM20);
TCCR2B = _BV(CS20);
TIMSK2 = _BV(TOIE2);
#endif
}


void setup() {
pinMode(PWM_PIN,OUTPUT);
audioOn();
pinMode(LED_PIN,OUTPUT);
}

void loop() {
// The loop is pretty simple - it just updates the parameters for the oscillators.
//
// Avoid using any functions that make extensive use of interrupts, or turn interrupts off.
// They will cause clicks and poops in the audio.

// Smooth frequency mapping
//syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL)) / 4;

// Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
//syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));

// Stepped pentatonic mapping: D, E, G, A, B
syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));

grainPhaseInc = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
grainDecay = analogRead(GRAIN_DECAY_CONTROL) / 8;
grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
grain2Decay = analogRead(GRAIN2_DECAY_CONTROL) / 4;
}

SIGNAL(PWM_INTERRUPT)
{
uint8_t value;
uint16_t output;

syncPhaseAcc += syncPhaseInc;
if (syncPhaseAcc < syncPhaseInc) {
// Time to start the next grain
grainPhaseAcc = 0;
grainAmp = 0x7fff;
grain2PhaseAcc = 0;
grain2Amp = 0x7fff;
LED_PORT ^= 1 << LED_BIT; // Faster than using digitalWrite
}

// Increment the phase of the grain oscillators
grainPhaseAcc += grainPhaseInc;
grain2PhaseAcc += grain2PhaseInc;

// Convert phase into a triangle wave
value = (grainPhaseAcc >> 7) & 0xff;
if (grainPhaseAcc & 0x8000) value = ~value;
// Multiply by current grain amplitude to get sample
output = value * (grainAmp >> 8);

// Repeat for second grain
value = (grain2PhaseAcc >> 7) & 0xff;
if (grain2PhaseAcc & 0x8000) value = ~value;
output += value * (grain2Amp >> 8);

// Make the grain amplitudes decay by a factor every sample (exponential decay)
grainAmp -= (grainAmp >> 8) * grainDecay;
grain2Amp -= (grain2Amp >> 8) * grain2Decay;

// Scale output to the available range, clipping if necessary
output >>= 9;
if (output > 255) output = 255;

// Output to PWM (this is faster than using analogWrite)
PWM_VALUE = output;
}

ESQUEMA Y FOTOS DEL PROCESO
Archivos adjuntos:
3038569386_fc884579a8_o.png
BBCode:
audu2.jpeg
BBCode:
audu1.jpeg
BBCode:
audu3.jpeg
BBCode:
audu6.jpeg
BBCode:
audu7.jpeg
BBCode:
audu8.jpeg
BBCode:
audu9.jpeg
BBCode:
audu13.jpeg
BBCode:
audu10.jpeg
BBCode:
Subir
1
#3 por Metamonodon el 28/01/2013
Yo estoy aprendiendo, este proyecto será lo siguiente después de probar con leds, le tenia el ojo echado. Gracias por compartir!
Subir
#4 por Man with the x-ray eyes el 28/01/2013
pues anímate, es muy fácil y el resultado mola mucho. Como decía este es el primer proyecto que hice, y funcionó a la primera!
Saludos!
Subir
1
#5 por Metamonodon el 05/02/2013
Eis, ya está. A la primera! Me falta saber que hace cada control, jajaja
Ahora le hecho un vistazo mas profundo al código y a posibles hacks.

Gracias por compartir!
Subir
#6 por Man with the x-ray eyes el 05/02/2013
Perfect! XD

Al principio del código te dice lo que es cada uno:
Analog in 0: Grain 1 pitch
// Analog in 1: Grain 2 decay
// Analog in 2: Grain 1 decay
// Analog in 3: Grain 2 pitch
// Analog in 4: Grain repetition frequency

Saludos!
Subir
1
#7 por Metamonodon el 05/02/2013
Ya, si lo vi, lo que tengo que mirar es la síntesis granular directamente xD
Subir
#8 por Metamonodon el 07/02/2013
Ya le he pillado el rollete, tenia un pote mal puesto.. suena genial por un mini ampli y con delay.

He estado mirando el foro de auduino en google y hay varias cosillas interesantes de midi, teclado, secuenciador, botón de cambio de escala..

Sabes de otros sintes o proyectos similares para arduino??

Estoy muy verde en el tema shields y electrónica, cualquier pista que me des será valida.

Saludos!
Subir
#9 por Man with the x-ray eyes el 07/02/2013
Ole!
yo hace tiempo lo probé pasándolo por el monotron, y sonaba supermarciano :desdentado:
En cuanto a sintes no lo cotrolo mucho, yo lo que he trasteado más ha sido el MIDI.
Sé que hay sitios como http://bleeplabs.com/ que venden kits de sintes basados en arduino (estos con el chip y el código, no la placa) y creo que también hay varias shields, pero ahora no las tengo controladas...
Sobre midi, colgué por aquí un par de proyectos básicos que con un poco de imaginación se pueden desarrollar fácilmente a algo más interesante:
- http://www.hispasonic.com/foros/paduino-01-pads-midi-basados-arduino/414667 : estos son un par de pads midi a modo de batería electrónica.
- http://www.hispasonic.com/foros/piano-midi-arduino/419226 este es algo similar, pero en vez de con pads, con pulsadores
- http://www.hispasonic.com/foros/drum-pad-arduino/419343 y aquí el proyecto más currado que hizo otro hispasónico a partir del anterior.

Espero que te sirva de algo...
Un saludo
Subir
#10 por Metamonodon el 07/02/2013
Mil gracias, con eso ya tengo para rato, si me entero de algo te lo hago saber.

Saludo!
Subir
1
#11 por Man with the x-ray eyes el 07/02/2013
cuando tenga un rato miro los marcadores que tengo en el otro ordena, que creo que tengo por ahí guardados algunos enlaces sobre sintes arduínicos...
:birras:
Subir
1
#12 por Metamonodon el 07/02/2013
Cuando puedas tío, sin prisas, que este es mi segundo sketch después de unos cuantos de bliking led
Subir
#13 por Man with the x-ray eyes el 07/02/2013
Bueno, lo que tenía por aquí guardado es poco y lo tengo en "cuentas pendientes" ya te digo que el tema de generar audio no lo he mirado mucho, pero es que esto de ser friki necesitaría dedicación plena :loco:
Un par de shields:
http://www.ginsingsound.com/
http://devsound.se/2012/sjs-one
y otro sinte que parece sencillito:
http://rcarduino.blogspot.com.es/2012/08/the-must-build-arduino-project-illutron.html

De esto no he probado nada, así que si te animas con algo, postea por aquí y anímanos!
Subir
#14 por Metamonodon el 08/02/2013
Si estoy en ello, estaba con Processing jugando con visuales, computer vision, etc.. y ahora me estoy pasando a esto. Estoy estudiando bellas artes que ahora incluye tambien estos temas "interactivos", pero claro, no es una ingeniería, estoy a base de internet con manuales básicos tipo getting started with.. y la verdad que me estoy enfricando bastante, mucho, gracias otra vez!
Subir
#15 por krlos16 el 01/05/2013
hola buenas noches, me gustaría saber si hay alguna forma de adaptar el código para que funcione con arduino leonardo, y por favor podrían mostrar mas detalladamente como hacer la conexión del audio jack ??? , soy nuevo en el tema. muchas gracias.
Subir
Respuesta rápida

Regístrate o para poder postear en este hilo