{"id":1269,"date":"2015-01-03T17:54:51","date_gmt":"2015-01-03T16:54:51","guid":{"rendered":"https:\/\/andyland.info\/wordpress\/?p=1269"},"modified":"2016-10-13T15:26:21","modified_gmt":"2016-10-13T14:26:21","slug":"arduino-audio-to-midi","status":"publish","type":"post","link":"https:\/\/andyland.info\/wordpress\/arduino-audio-to-midi\/","title":{"rendered":"Arduino Audio-To-Midi"},"content":{"rendered":"<p>Or: Creating an audio-signal with an Arduino, feeding it into a mixing desk, altering the frequencies via the mixer&#8217;s eq and analyzing the processed audio with another Arduino which then turns it into a MIDI-signal. Yes, that is Digital-to-Analog-to-Digital-to-Analog-to-Digital-conversion. Phew!<\/p>\n<p>Here&#8217;s a picture of the setup:<\/p>\n<p><a href=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1265\" src=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954-1024x768.jpg\" alt=\"CIMG9954\" width=\"800\" height=\"600\" srcset=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954-1024x768.jpg 1024w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954-300x225.jpg 300w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954-200x150.jpg 200w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9954-150x113.jpg 150w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>On the left side there is a circuit consisting of an Arduino and an Attiny85. The Arduino creates a low-frequency ( &#8216;bass&#8217; ) sine-shaped tone which perfectly sits in the frequency range of the mixer&#8217;s bass-EQ. I did some testing here to find the perfect frequency. Testing means: Using Ableton Live to create a white noise, feed this into the mixer, feed the mixer&#8217;s output back into Ableton and use the Spectrum-tool to see which frequency gets most influenced by the bass-EQ (C2, that is).<\/p>\n<p>Creating a somewhat true sine needs some effort since the Arduino&#8217;s analog outputs only do PWM which isn&#8217;t very useful when talking about low-frequency audio signals. PWM basically creates a square-wave signal with a certain pulse-pause relation. While this might be okay for dimming an LED, this becomes quite unusable when dealing with audio because you can simply hear that it&#8217;s no sine &#8211; the lower the frequency the more the signal turns into some sort of &#8216;click&#8217;-noise. No wonder, the bass-EQ doesn&#8217;t influence this to any convience.<\/p>\n<p>That&#8217;s why I used <a href=\"http:\/\/interface.khm.de\/index.php\/lab\/interfaces-advanced\/arduino-dds-sinewave-generator\/\">this<\/a> solution to make the Arduino spit out something that&#8217;s a little more sinewave-like. I ommitted the circuit as you may see on the picture below. I didn&#8217;t have the necessary parts lying around and it worked nevertheless.<\/p>\n<p>The Attiny85 is used to create the second tone. It&#8217;s a simple PWM signal at 480 Hz. This time the PWM-nature of the signal can be used for our benefits: A square-wave signal has a recognizable amount of harmonics. You don&#8217;t hear one but (at least) two tones. Perfect for us because the mixer I used perfectly\u00a0influences (well &#8230; &#8220;perfectly&#8221; )\u00a0 the signals with its mid- and hi-EQs.<\/p>\n<p>&nbsp;<\/p>\n<p>The code for the Attiny85 looks like this:<\/p>\n<p>void setup(){<br \/>\npinMode(3, OUTPUT);<br \/>\n}<\/p>\n<p>void loop(){<br \/>\nbuzz(3,480,100);<br \/>\n}<\/p>\n<p>void buzz(int targetPin, long frequency, long length) {<br \/>\nlong delayValue = 1000000\/frequency\/2; \/\/ calculate the delay value between transitions<br \/>\nlong numCycles = frequency * length\/ 1000; \/\/ calculate the number of cycles for proper timing<br \/>\nfor (long i=0; i &lt; numCycles; i++){ \/\/ for the calculated length of time&#8230;<br \/>\ndigitalWrite(targetPin,HIGH); \/\/ write the buzzer pin high to push out the diaphram<br \/>\ndelayMicroseconds(delayValue); \/\/ wait for the calculated delay value<br \/>\ndigitalWrite(targetPin,LOW); \/\/ write the buzzer pin low to pull back the diaphram<br \/>\ndelayMicroseconds(delayValue); \/\/ wait again or the calculated delay value<br \/>\n}<br \/>\n}<\/p>\n<p>I guess I found it over <a href=\"http:\/\/www.princetronics.com\/supermariothemesong\/\">here<\/a> and adapted it to my needs.<\/p>\n<p>the two microcontroller&#8217;s output signals are fed into a 7408 (Quad AND) and then sent out into the analog world by a circuit I found over at the <a href=\"https:\/\/wiki.munichmakerlab.de\/wiki\/Auduino\">MunichMakerLab.<\/a> This is my first audio-circuit with an Arduino. it&#8217;s probably spine-crawling for those who do this on a more professional base but I was getting the best results with this circuit.<\/p>\n<p>[Edit] As someone pointed out in the comments section for this post on <a href=\"http:\/\/www.hackaday.com\">Hackaday<\/a> this might read\u00a0like I didn&#8217;t know at all what I am doing here or that it&#8217;s all just a big coincidence. This is not correct. The AND gate protects\u00a0the audio sources from interfering with each other for a certain amount. I tested that, it simply sounds cleaner. At least I had a certain intention when I added the gates to the circuit (&#8230;not that I completely remember&#8230;.). Looking at the circuit I am still wandering about _why_ but that&#8217;s one of the things that I file as &#8216;Audio things&#8217; for now. [\/Edit]<\/p>\n<p><a href=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1264\" src=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964-1024x768.jpg\" alt=\"CIMG9964\" width=\"800\" height=\"600\" srcset=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964-1024x768.jpg 1024w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964-300x225.jpg 300w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964-200x150.jpg 200w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9964-150x113.jpg 150w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>The signal is fed into the mixer and from the mixer sent to another Arduino which does the processing. the circuit looks like this:<\/p>\n<p><a href=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1263\" src=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963-1024x768.jpg\" alt=\"CIMG9963\" width=\"800\" height=\"600\" srcset=\"https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963-1024x768.jpg 1024w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963-300x225.jpg 300w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963-200x150.jpg 200w, https:\/\/andyland.info\/wordpress\/wp-content\/uploads\/CIMG9963-150x113.jpg 150w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>To be honest: I cannot really remember where I got this circuit from. Somehow all the solutions I found while trying to find the circuit again look a little different. Again this might be spine.crawling for some of you but&#8230; it&#8217;s a fun project and it works. The code for the realtime audio-analysis is based on the FHT library by <a href=\"http:\/\/www.openmusiclabs.com\">openmusiclabs<\/a> and expands an example I found over at <a href=\"http:\/\/dqydj.net\/build-your-own-real-time-frequency-analyzer-and-christmas-light-controller\/\">dontquityourdayjob<\/a>.<\/p>\n<p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\n\/\/ Easy Customizations<br \/>\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p>\n<p>\/\/ Adjust the Treshold &#8211; what volume should make it light up?<br \/>\n#define THRESHOLD 40<br \/>\n\/\/ Attempt to &#8216;zero out&#8217; noise when line in is &#8216;quiet&#8217;.\u00a0 You can change this to make some segments more sensitive.<br \/>\nint\u00a0 oct_bias[] = { 600, 600, 1, 100, 50, 50, 50, 50\u00a0 };<br \/>\n\/\/ Divide Threshold by 2 for top octave? 1 &#8211; yes 2 &#8211; no.\u00a0 Makes highest frequency blink more.<br \/>\n#define TOP_OCTAVE_DIVIDE false<\/p>\n<p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\n\/\/ Hard Customizations &#8211; know what you are doing, please.<br \/>\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\n\/\/ FHT defaults &#8211; don&#8217;t change without reading the Open Music Labs documentation at openmusiclabs.com<br \/>\n#define LOG_OUT 0 \/\/ use the log output function<br \/>\n#define FHT_N 256 \/\/ set to 256 point fht<br \/>\n#define OCTAVE 1<br \/>\n#define OCT_NORM 1<\/p>\n<p>\/\/ Delay &#8211; defines how many cycles before the lights will update.\u00a0 OML&#8217;s algorithm at 256 samples (needed for our 8 octaves) takes<br \/>\n\/\/ 3.18 ms per cycle, so we essentially throw out 14 cycles (I used mechanical relays, you can lower this for solid state relays).<br \/>\n\/\/ 15 cycles = 47.7 ms update rate.\u00a0 Be careful here and don&#8217;t change it too quickly!\u00a0 I warned you!<br \/>\n#define DELAY 15<br \/>\n#include &lt;FHT.h&gt; \/\/ include the library<br \/>\n#include &lt;MIDI.h&gt;<\/p>\n<p>void setup() {<br \/>\nSerial.begin(31250); \/\/ use the serial port<br \/>\nTIMSK0 = 0; \/\/ turn off timer0 for lower jitter<br \/>\nADCSRA = 0xe5; \/\/ set the adc to free running mode<br \/>\nADMUX = 0x40; \/\/ use adc0<br \/>\nDIDR0 = 0x01; \/\/ turn off the digital input for adc0<br \/>\n}<\/p>\n<p>\/**********************************************************************************<br \/>\nLoop &#8211; includes initialization function and the full loop<br \/>\n**********************************************************************************\/<br \/>\nconst int NUMREADINGS=10;<br \/>\nint readings[NUMREADINGS];\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ the readings from the analog input<br \/>\nint index = 0;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ the index of the current reading<br \/>\nint total = 0;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ the running total<br \/>\nint average = 0;<\/p>\n<p>int bassVal;<br \/>\nint midVal;<br \/>\nint hiVal;<\/p>\n<p>int bassValOld;<br \/>\nint midValOld;<br \/>\nint hiValOld;<\/p>\n<p>const int OUTTHRESHHOLD = 4;<\/p>\n<p>void loop() {<br \/>\n\/\/ True full loop<br \/>\nint q = 0;<br \/>\nwhile(1) { \/\/ reduces jitter<br \/>\ncli();\u00a0 \/\/ UDRE interrupt slows this way down on arduino1.0<br \/>\nfor (int i = 0 ; i &lt; FHT_N ; i++) { \/\/ save 256 samples<br \/>\nwhile(!(ADCSRA &amp; 0x10)); \/\/ wait for adc to be ready<br \/>\nADCSRA = 0xf5; \/\/ restart adc<br \/>\nbyte m = ADCL; \/\/ fetch adc data<br \/>\nbyte j = ADCH;<br \/>\nint k = (j &lt;&lt; 8) | m; \/\/ form into an int<br \/>\nk -= 0x0200; \/\/ form into a signed int<br \/>\nk &lt;&lt;= 6; \/\/ form into a 16b signed int<br \/>\nfht_input[i] = k; \/\/ put real data into bins<br \/>\n}<br \/>\nfht_window(); \/\/ window the data for better frequency response<br \/>\nfht_reorder(); \/\/ reorder the data before doing the fht<br \/>\nfht_run(); \/\/ process the data in the fht<br \/>\nfht_mag_octave(); \/\/ take the output of the fht<\/p>\n<p>sei();<br \/>\nif (q % DELAY == 0) {<br \/>\n\/\/&#8212;-Smoothing<br \/>\n\/\/ subtract the last reading:<br \/>\ntotal= total &#8211; readings[index];<br \/>\n\/\/ read from the sensor:<br \/>\nreadings[index] = (fht_oct_out[1] &#8211; oct_bias[1]);<br \/>\n\/\/ add the reading to the total:<br \/>\ntotal= total + readings[index];<br \/>\n\/\/ advance to the next position in the array:<br \/>\nindex = index + 1;<\/p>\n<p>\/\/ if we&#8217;re at the end of the array&#8230;<br \/>\nif (index &gt;= NUMREADINGS)<br \/>\n\/\/ &#8230;wrap around to the beginning:<br \/>\nindex = 0;<\/p>\n<p>\/\/ calculate the average:<br \/>\naverage = total \/ NUMREADINGS;<br \/>\n\/\/&#8212;-<\/p>\n<p>\/\/Werte:<br \/>\nbassVal = average;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ : Bass<br \/>\nmidVal = fht_oct_out[4] &#8211; oct_bias[4];\u00a0\u00a0\u00a0 \/\/ Mitte<br \/>\nhiVal = fht_oct_out[7] &#8211; oct_bias[7];\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Hochton<\/p>\n<p>bassVal = map(bassVal, -450, -390, 0, 127);<br \/>\nmidVal = map(midVal, 9, 107, 0, 127);<br \/>\nhiVal = map(hiVal, -34, 20, 0, 127);<\/p>\n<p>if((bassVal &gt; bassValOld+OUTTHRESHHOLD) || (bassVal &lt; bassValOld-OUTTHRESHHOLD)){<br \/>\nif((bassVal&gt;=0) &amp;&amp; (bassVal&lt;=127)){<br \/>\nSerial.write(0xb0);<br \/>\nSerial.write(0x01);<br \/>\nSerial.write(bassVal);<br \/>\n}<br \/>\nbassValOld = bassVal;<br \/>\n}<\/p>\n<p>if((midVal &gt; midValOld+OUTTHRESHHOLD) || (midVal &lt; midValOld-OUTTHRESHHOLD)){<br \/>\nif((midVal&gt;=0) &amp;&amp; (midVal&lt;=127)){<br \/>\nSerial.write(0xb0);<br \/>\nSerial.write(0x02);<br \/>\nSerial.write(midVal);<br \/>\n}<br \/>\nmidValOld = midVal;<br \/>\n}<\/p>\n<p>if((hiVal &gt; hiValOld+OUTTHRESHHOLD) || (hiVal &lt; hiValOld-OUTTHRESHHOLD)){<br \/>\nif((hiVal&gt;=0) &amp;&amp; (hiVal&lt;=127)){<br \/>\nSerial.write(0xb0);<br \/>\nSerial.write(0x03);<br \/>\nSerial.write(hiVal);<br \/>\n}<br \/>\nhiValOld = hiVal;<br \/>\n}<br \/>\n}<br \/>\n++q;<br \/>\n}<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<p>The whole mechanism is not THAT precise but it gets the job done and it&#8217;s a fun thing to watch. The bass-frequency has to be smoothed-out quite a bit in order to make it all work. After spending a little more than a day with this some might ask &#8220;what for?&#8221;. I tell you what for: for the sake of finally doing it. I had this idea for over a year now and it was well worth trying.<\/p>\n<p>The system is quite slow in its reaction (mainly caused by the necessary smoothing) and results are still a bit unpredictable but turning an audio-mixer into a midi-controller just by using hardware of ~10\u20ac ain&#8217;t too bad, isn&#8217;t it?<\/p>\n<p>&nbsp;<\/p>\n<p>[tube]https:\/\/www.youtube.com\/watch?v=u5r6i65eHKk, 720, 540[\/tube]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Or: Creating an audio-signal with an Arduino, feeding it into a mixing desk, altering the frequencies via the mixer&#8217;s eq and analyzing the processed audio with another Arduino which then turns it into a MIDI-signal. Yes, that is Digital-to-Analog-to-Digital-to-Analog-to-Digital-conversion. Phew! Here&#8217;s a picture of the setup: On the left side \u2026 <a class=\"continue-reading-link\" href=\"https:\/\/andyland.info\/wordpress\/arduino-audio-to-midi\/\"> Continue reading <span class=\"meta-nav\">&rarr; <\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[5],"tags":[54,87,35],"class_list":["post-1269","post","type-post","status-publish","format-standard","hentry","category-projekte","tag-arduino","tag-audio","tag-midi","odd"],"_links":{"self":[{"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/posts\/1269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/comments?post=1269"}],"version-history":[{"count":0,"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/posts\/1269\/revisions"}],"wp:attachment":[{"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/media?parent=1269"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/categories?post=1269"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andyland.info\/wordpress\/wp-json\/wp\/v2\/tags?post=1269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}