Tue, 23/11/2010 - 10:06 · per santi
hav1bit

Hav1bit

HAV1BIT, Primer Sintetitzador Audiovisual fet per Telenoika, de la mà dels Luthiers Drapaires

HAV1BIT és un sintetitzador audiovisual d’1 bit de hardware obert basat en arduino, té una sortida minijack, una VGA (640*480px) i 6 potenciometres+6 botons. Són 3 oscil·ladors d’ona quadrada que es modulen entre si, una espècie d’aproximació a la síntesi FM, però audiovisual. Cada oscil·lador modula un dels canals de color RGB.

Ara mateix podeu veure l'esquema, el codi, la descripció i un vídeo d'exemple d'aquest sinte en fase beta, tot i que ja s'està treballant en les noves funcionalitats que se li volen donar:

-guardat de presets
-seqüenciació via serial amb maxforlive o midi (a través del port usb)
-manipulació de senyal de sincronia
-possible mode 8 bits

Tot el disseny està basat en Arduino, amb col·laboració de molts membres de la comunitat a través dels forums. El aparell té unes quantes funcionalitats interessants:

Modes de funcionament:

-Simple: control gruix (ms) i fi (microsegons) de la frequencia dels osciladors
-Rampes: generació de rampes (ones de serra) amb estat inicial, estat final, i temps de la rampa ajustables (moltes gràcies al Emannuelle Mazza pel codi d’aquesta part!)
-Random: frequencia aleatoria per canal, dins un rang definible i amb canvi cada temps definit
-Rampes+Random: Una mescla extraterrestre de les dos funcionalitats anteriors

Connectivitat

-L’aparell pot funcionar de forma autònoma, mitjançant una interfície amb 6 switches i 6 potenciometres
-Es pot connectar a través d’USB a un ordinador i controlar la síntesi a través del port Serial. Estem treballant en un patch per a PureData que permetrà fer MOLTES coses guapes.

DIY

-Com sempre, els nostres dissenys son en part depenents del coneixements que altres han estat a bé compartir, així que en retorn a la comunitat aqui va tot el necessàri per a construir-se’n un d’aquests:

sinte-schem

La construcció és molt fàcil, nomes cal 6 botons i 6 potenciometres connectats a arduino, a més del port minijack i el port VGA.

El Firmware el podeu descarregar a continuació: AV3.pde

  1. //AV1BIT Audiovisual MonoChord 1Bit Synthesizer
  2.  
  3. //VGA Sync Generator by DWAN
  4. //Faster AnalogRead code by jmknapp
  5. //Ramps code by Emanuelle Mazza
  6.  
  7.  
  8.  
  9. /* VGA Sync Generator
  10.  * 11/11/08 - dwan : dwanafite@yahoo.fr
  11.  *
  12.  * Based on :
  13.  * - RG Matrix Example v.2 8/1/08, by BroHogan, from the Arduino Playground
  14.  * - Simplest universal VGA/PAL terminal, by Ibragimov Maxim Rafikovich, http://www.vga-avr.narod.ru/main.html
  15.  * - the very useful Timer/Counter/Prescaler Calculator, http://www.et06.dk/atmega_timers/
  16.  * - Arduino.cc Port Manipulation Tutorial
  17.  *
  18.  * This program outputs pretty accurate VGA syncronization signals. It's using a timer interrupt on timer2, so hopefully you can make other cool things in loop().
  19.  */
  20.  
  21. // 640 * 480 @ 60Hz - FvSync = 60.3 Hz / FhSync = 31.3 kHz
  22. // HSync : pin 7 Arduino, pin 13 VGA
  23. // VSync : pin 6 Arduino, pin 14 VGA
  24. // Arduino's pin 5 is HIGH when video can be sent, LOW otherwise. I use it to power a transistor. See this wonderful page : http://www.anatekcorp.com/driving.htm
  25. // 1 NOP = 62,5 ns wasted
  26.  
  27. #define NOP asm("nop")
  28.  
  29. #define vga_field_line_count 525 // number of VGA lines
  30. #define ISR_FREQ 0x3F // Sets the speed of the ISR - LOWER IS FASTER - 62
  31.  
  32. volatile unsigned int linecount;
  33.  
  34.  
  35.  
  36.  
  37. //FASTER ANALOG READS
  38. //Prescaler/16 (faster analogReads)
  39. #define FASTADC 1
  40.  
  41. // defines for setting and clearing register bits
  42. #ifndef cbi
  43. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  44. #endif
  45. #ifndef sbi
  46. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  47. #endif
  48.  
  49.  
  50.  
  51.  
  52. // Pins per a sortida (RGB i à udio):
  53. const byte R = 9;
  54. const byte G = 10;
  55. const byte B = 11;
  56.  
  57. const byte A = 12;
  58.  
  59.  
  60. //pins d'entrada digital (switch)
  61. const int Rswitch1 = 1; // output as an input
  62. const int Rswitch2 = 4; // output as an input
  63.  
  64. const int Gswitch1 = 2; // output as an input
  65. const int Gswitch2 = 5; // output as an input
  66.  
  67. const int Bswitch1 = 3; // output as an input
  68. const int Bswitch2 = 8; // output as an input
  69.  
  70. const int Randomizer = 13;
  71.  
  72.  
  73. // Variables d'estat:
  74. byte RState = LOW;
  75. byte GState = LOW;
  76. byte BState = LOW;
  77.  
  78. unsigned long previousMicros=0;
  79. unsigned long previousMillis=0;
  80. unsigned long interval=0;
  81.  
  82.  
  83. //declara temps d'inicialitzacio de les rampes
  84. long unsigned int initRamp1;
  85. long unsigned int initRamp2;
  86. long unsigned int initRamp3;
  87.  
  88.  
  89. //Llegeix els potes
  90. unsigned long int Rpote1(){
  91. unsigned long int r= analogRead(0);
  92. return r;
  93. }
  94.  
  95. unsigned long int Rpote2(){
  96. unsigned long int r= analogRead(3);
  97. return r;
  98. }
  99.  
  100. unsigned long int Gpote1(){
  101. unsigned long int g= analogRead(1);
  102. return g;
  103. }
  104.  
  105. unsigned long int Gpote2(){
  106. unsigned long int g= analogRead(4);
  107. return g;
  108. }
  109.  
  110. unsigned long int Bpote1(){
  111. unsigned long int b= analogRead(2);
  112. return b;
  113. }
  114.  
  115. unsigned long int Bpote2(){
  116. unsigned long int b= analogRead(5);
  117. return b;
  118. }
  119.  
  120.  
  121. //declara randoms
  122. int random1=0;
  123. int random2=0;
  124. int random3=0;
  125.  
  126.  
  127.  
  128. void setup()
  129. {
  130. // Serial.begin(115200);
  131.  
  132. DDRD |= B11100000; // it sets pins 7, 6 and 5 as output without changing the value of pins 0 & 1, which are RX & TX
  133. // 76543210 <- pin translation
  134.  
  135. PORTD |= B11000000; // sets pins 7 (hSync) and 6 (vSync) HIGH
  136. // 76543210;
  137.  
  138. setISRtimer(); // setup the timer
  139. startISR(); // start the timer to toggle shutdown
  140.  
  141.  
  142.  
  143. // set prescale to 16: faster analog reads
  144. #if FASTADC
  145. sbi(ADCSRA,ADPS2) ;
  146. cbi(ADCSRA,ADPS1) ;
  147. cbi(ADCSRA,ADPS0) ;
  148. #endif
  149.  
  150.  
  151. pinMode(R, OUTPUT);
  152. pinMode(G, OUTPUT);
  153. pinMode(B, OUTPUT);
  154.  
  155. pinMode(Rswitch1, INPUT);
  156. pinMode(Rswitch2, INPUT);
  157. pinMode(Gswitch1, INPUT);
  158. pinMode(Gswitch2, INPUT);
  159. pinMode(Bswitch1, INPUT);
  160. pinMode(Bswitch2, INPUT);
  161.  
  162. pinMode(Randomizer, INPUT);
  163.  
  164. initRamp1 = millis();
  165. initRamp2 = millis();
  166. initRamp3 = millis();
  167. }
  168.  
  169.  
  170.  
  171. void loop()
  172. {
  173.  
  174. long unsigned int a= Rpote1();
  175. long unsigned int b= Rpote2();
  176. long unsigned int c= Gpote1();
  177. long unsigned int d= Gpote2();
  178. long unsigned int e= Bpote1();
  179. long unsigned int f= Bpote2();
  180.  
  181. if (a+b <=2044){
  182. Rswitch(a,b);
  183. }
  184.  
  185. if (c+d <=2044){
  186. Gswitch(c,d);
  187. }
  188.  
  189. if (e+f <=2044){
  190. Bswitch(e,f);
  191. }
  192. }
  193.  
  194.  
  195. //Gestio dels modes de funcionament (a través dels switches)
  196. void Rswitch(long unsigned int pote1, long unsigned int pote2){
  197.  
  198. byte Rsw1 = digitalRead(Rswitch1);
  199. byte Rsw2 = digitalRead(Rswitch2);
  200.  
  201. if (Rsw1==HIGH && Rsw2==HIGH){
  202. RandRampR(pote1, pote2);
  203. }
  204.  
  205. if (Rsw1==HIGH && Rsw2==LOW){
  206. RampR(pote1, pote2);
  207. }
  208.  
  209. if (Rsw1==LOW && Rsw2==LOW){
  210. SimpleR(pote1, pote2);
  211. }
  212.  
  213. if (Rsw1==LOW && Rsw2==HIGH){
  214. RandomR(pote1, pote2);
  215. }
  216. }
  217.  
  218.  
  219. void Gswitch(long unsigned int pote1, long unsigned int pote2){
  220.  
  221. byte Gsw1 = digitalRead(Gswitch1);
  222. byte Gsw2 = digitalRead(Gswitch2);
  223.  
  224.  
  225. if (Gsw1==HIGH && Gsw2==HIGH){
  226. RandRampG(pote1, pote2);
  227. }
  228.  
  229. if (Gsw1==HIGH && Gsw2==LOW){
  230. RampG(pote1, pote2);
  231. }
  232.  
  233. if (Gsw1==LOW && Gsw2==LOW){
  234. SimpleG(pote1, pote2);
  235. }
  236.  
  237. if (Gsw1==LOW && Gsw2==HIGH){
  238. RandomG(pote1, pote2);
  239. }
  240. }
  241.  
  242.  
  243. void Bswitch(long unsigned int pote1, long unsigned int pote2){
  244.  
  245. byte Bsw1 = digitalRead(Bswitch1);
  246. byte Bsw2 = digitalRead(Bswitch2);
  247.  
  248.  
  249. if (Bsw1==HIGH && Bsw2==HIGH){
  250. RandRampB(pote1, pote2);
  251. }
  252.  
  253. if (Bsw1==HIGH && Bsw2==LOW){
  254. RampB(pote1, pote2);
  255. }
  256.  
  257. if (Bsw1==LOW && Bsw2==LOW){
  258. SimpleB(pote1, pote2);
  259. }
  260.  
  261. if (Bsw1==LOW && Bsw2==HIGH){
  262. RandomB(pote1, pote2);
  263. }
  264.  
  265. }
  266.  
  267.  
  268. //Modes de funcionament
  269.  
  270. void RampR(long unsigned int a, long unsigned int b){
  271. SimpleR(0,ramp1(0,a*100,b*10));
  272. }
  273.  
  274. void RandomR(long unsigned int a, long unsigned int b){
  275. SimpleR(0,randomize1(a*100,b));
  276. }
  277.  
  278. void RandRampR(long unsigned int a, long unsigned int b){
  279. SimpleR(0,randomize1(a*50,0)+ramp1(0,50000,b));
  280. }
  281.  
  282. void RampG(long unsigned int a, long unsigned int b){
  283. SimpleG(0,ramp2(0,a*100,b*10));
  284. }
  285.  
  286. void RandomG(long unsigned int a, long unsigned int b){
  287. SimpleG(0,randomize2(a*100,b));
  288. }
  289.  
  290. void RandRampG(long unsigned int a, long unsigned int b){
  291. SimpleG(0,randomize2(a*50,0)+ramp2(0,50000,b));
  292. }
  293.  
  294. void RampB(long unsigned int a, long unsigned int b){
  295. SimpleB(0,ramp3(0,a*100,b*10));
  296. }
  297.  
  298. void RandomB(long unsigned int a, long unsigned int b){
  299. SimpleB(0,randomize3(a*100,b));
  300. }
  301.  
  302. void RandRampB(long unsigned int a, long unsigned int b){
  303. SimpleB(0,randomize3(a*50,0)+ramp3(0,50000,b));
  304. }
  305.  
  306.  
  307.  
  308. ////modes Simples
  309. void SimpleR(long unsigned int a, long unsigned int b){
  310.  
  311. unsigned long int rdel=(a*500)+b;
  312. unsigned long currentMicros = micros();
  313.  
  314. if (micros() - previousMicros >= rdel) {
  315. previousMicros = previousMicros+rdel;
  316.  
  317. if (rdel <512000){
  318. RState =! RState;
  319.  
  320. digitalWrite(R, RState);
  321. digitalWrite(A, RState);
  322. }
  323. }
  324. }
  325.  
  326.  
  327.  
  328. void SimpleG(long unsigned int a, long unsigned int b){
  329.  
  330. unsigned long int gdel=(a*500)+b;
  331. unsigned long currentMicros = micros();
  332.  
  333. if (micros() - previousMicros >= gdel) {
  334. previousMicros = previousMicros+gdel;
  335.  
  336. if (gdel <512000){
  337. GState =! GState;
  338.  
  339. digitalWrite(G, GState);
  340. digitalWrite(A, GState);
  341. }
  342. }
  343. }
  344.  
  345. void SimpleB(long unsigned int a, long unsigned int b){
  346.  
  347. unsigned long int bdel=(a*500)+b;
  348. unsigned long currentMicros = micros();
  349.  
  350. if (micros() - previousMicros >= bdel) {
  351. previousMicros = previousMicros+bdel;
  352.  
  353. if (bdel <512000){
  354. BState =! BState;
  355.  
  356. digitalWrite(B, BState);
  357. digitalWrite(A, BState);
  358. }
  359. }
  360. }
  361.  
  362.  
  363.  
  364.  
  365. /////Rampes
  366.  
  367. unsigned int ramp1(unsigned int inicio, unsigned int fin, long unsigned int duracion){
  368.  
  369. unsigned int frecuencia = inicio;
  370.  
  371. if((millis() - initRamp1) < duracion){
  372. frecuencia = map((millis() - initRamp1),0,duracion,inicio,fin);
  373. }else{
  374. initRamp1 = millis();
  375. }
  376.  
  377. return frecuencia;
  378.  
  379. }
  380.  
  381.  
  382. unsigned int ramp2(unsigned int inicio, unsigned int fin, long unsigned int duracion){
  383.  
  384. unsigned int frecuencia = inicio;
  385.  
  386. if((millis() - initRamp2) < duracion){
  387. frecuencia = map((millis() - initRamp2),0,duracion,inicio,fin);
  388. }else{
  389. initRamp2 = millis();
  390. }
  391.  
  392. return frecuencia;
  393.  
  394. }
  395.  
  396.  
  397. unsigned int ramp3(unsigned int inicio, unsigned int fin, long unsigned int duracion){
  398.  
  399. unsigned int frecuencia = inicio;
  400.  
  401. if((millis() - initRamp3) < duracion){
  402. frecuencia = map((millis() - initRamp3),0,duracion,inicio,fin);
  403. }else{
  404. initRamp3 = millis();
  405. }
  406.  
  407. return frecuencia;
  408.  
  409. }
  410.  
  411.  
  412.  
  413. ///Randomitzador
  414.  
  415. int randomize1(unsigned int v, unsigned int n){
  416.  
  417. if (millis() - previousMillis >= n) {
  418. previousMillis = previousMillis+n;
  419.  
  420. random1=random(v);
  421. }
  422. return random1;
  423. }
  424.  
  425. int randomize2(unsigned int v, unsigned int n){
  426.  
  427. if (millis() - previousMillis >= n) {
  428. previousMillis = previousMillis+n;
  429.  
  430. random2=random(v);
  431. }
  432. return random2;
  433. }
  434.  
  435. int randomize3(unsigned int v, unsigned int n){
  436.  
  437. if (millis() - previousMillis >= n) {
  438. previousMillis = previousMillis+n;
  439.  
  440. random3=random(v);
  441. }
  442. return random3;
  443. }
  444.  
  445.  
  446.  
  447. //Timer per a VGA
  448. ///////////////////////////// ISR Timer Functions ///////////////////////////
  449. ISR(TIMER2_COMPA_vect)
  450. {
  451. // Stop video
  452. // pin 5 LOW
  453. PORTD &= ~(1 << 5);
  454.  
  455. // Front porch
  456. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  457.  
  458.  
  459. // Count number of lines
  460. if (++linecount == vga_field_line_count)
  461. {
  462. linecount = 0;
  463. }
  464.  
  465. // can it be vsync tiem nao ?
  466. if ((linecount == 10 )||(linecount == 11 ))
  467. {
  468. // hsync LOW
  469. // vsync LOW
  470. PORTD &= ~(1 << 7);
  471. PORTD &= ~(1 << 6);
  472. }
  473. else // ,hsync only
  474. {
  475. // hsync LOW
  476. // vsync HIGH
  477. PORTD &= ~(1 << 7);
  478. PORTD |= (1 << 6);
  479. }
  480.  
  481. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  482. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  483. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  484. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  485.  
  486. // nonetheless,
  487. // hsync HIGH
  488. PORTD |= (1 << 7);
  489.  
  490. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  491. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  492. NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
  493. NOP;
  494.  
  495. // Start video if we are in a visible area
  496. if (linecount > 45)
  497. {
  498. // pin 5 HIGH
  499. PORTD |= (1 << 5);
  500. }
  501. }
  502.  
  503. void setISRtimer(){ // setup ISR timer controling toggleing
  504. TCCR2A = 0x02; // WGM22=0 + WGM21=1 + WGM20=0 = Mode2 (CTC)
  505. TCCR2B = (1 << CS01); // /8 prescaler (2MHz)
  506. TCNT2 = 0; // clear counter
  507. OCR2A = ISR_FREQ; // set TOP (divisor) - see #define
  508. }
  509.  
  510. void startISR(){ // Starts the ISR
  511. TCNT2 = 0; // clear counter (needed here also)
  512. TIMSK2|=(1<<OCIE2A); // set interrupts=enabled (calls ISR(TIMER2_COMPA_vect)
  513. }
  514.  
  515. void stopISR(){ // Stops the ISR
  516. TIMSK2&=~(1<<OCIE2A); // disable interrupts
  517. }

Actualitzacions:

Anirem actualitzant el firmware de la màquina, afegint-hi noves funcionalitats.

Tenim en ment implementar un sistema de gravació de presets i un sistema de sequenciació per midi. Mica en mica anirem afegint aquestes coses a la web, estigeu atents si us interessa.

Recursos Externs

  • Schlieren :: enregistrar ones de so i calor

    La fotografia Schlieren és una tècnica que permet captar el so o la calor.

    Es capten les variacions en la densitat d'un fluid (l'aire en aquest cas) generades pel so o la calor. Aquestes variacions es coneixen com l'efecte Schlieren, i van ser descobertes pel físic alemany August Toepler al 1864.

    clap
  • Moss FM

    Han arrribat les piles-planta!


    És un fet conegut que les plantes generen electricitat en petites quantitats.


    Un grup de recerca de la Universitat de Cambridge ens han fet arribar aquest vídeo on fan funcionar una ràdio ::
    (Font: http://wired.com/design/2014/03/moss-solar-panels-power-pocket-radio)

    moss fm
  • Valve Open-Sources Their Direct3D To OpenGL Translation Layer

    With Valve's Source Engine originally just targeting Direct3D, when initially porting their games to Linux and OS X they relied upon a hand-made Direct3D to OpenGL translation layer. In potentially assisting other game developers, Valve Software has now opened up this graphics translation layer.

    valve
  • riot-NAS: Almacenamiento móvil para fotografía de calle

    Dispositivo portátil que permita almacenar un respaldo de las fotografías que se tomen con teléfonos celulares cercanos.


    El principal objetivo es preservar la información (videos y fotografías) que sean tomadas por los asistentes a grandes concentraciones de personas, de tal forma que en caso de perdida o robo del equipo o de que su propietario sea obligado a borrar la información local en el dispositivo, esta información sea conservada para posterior uso en redes sociales o periodismo ciudadano.

    riot-nas
  • AratechLabs presents Polarmic

    AratechLabs, http://www.aratechlabs.com , a catalan start-up, introduces new Augmented Reality application:


    Arapolarmic


    It helps sound technicians and musicians to visualize the directional polar patterns of microphones, with a tablet device that captures and matches microphones and shows the patterns on the screen.

    Ara PolarMic Augmented reality application for microphone directivity monitoring

Recursos comunitAV

  • Kickstarter - FPV Live Streaming Paper Airplane Drone

    kickstarter powerup-fpv-live-streaming-paper-airplane-drone

    Acerca de este proyecto

    It’s a bird. It’s a plane. Well, sort of. It’s you, flying atop your very own paper airplane... It’s PowerUp FPV: the first ever paper airplane drone with a live streaming camera!

    paper drone FPV stream
  • Desbloquear celdas protegidas en documentos excel

    Para desbloquear celdas que no nos permiten escribir porque estan bloqueadas por un password que no conocemos, se puede seguir el siguiente procedimiento:

    Guardar el fichero con un formato abierto, un fichero.ODS por ejemplo. Este formato es en realidad un zip con varios ficheros dentro.

    Cambiar la extension de .ODS a .ZIP y descomprimir el contenido en una carpeta.

  • Listening-Lights

    Andrés Pérez López

    Sound and Light Free software tools for sound and lighting synchronization

    Presentació a Telenoika: https://vimeo.com/117961054

    Listening-Lights - Machine Listening for Lighting Synchronization

    Dependencies:

    sc3 plugins
    SCMIR (http://composerprogrammer.com/code/SCMIR.zip)

    Examples:

  • synthpibots

    Xavi manzanares

    Synth > Synths // Sintetitzadors
    Pi > RaspberryPi platform // Plataforma Raspberry Pi
    BØTS > Generative compositions of light and sound // Composicions generatives de so i llum

    tira3DPrint+Pètals

    Abstract