Using Mozzi to process analogRead's?

543 views
Skip to first unread message

loss1234

unread,
Mar 17, 2013, 9:28:45 AM3/17/13
to mozzi...@googlegroups.com
I am really excited about Mozzi! One of the things I am most impressed by are the wide variety of good sounding audio tools within the library.
I have been involved in making synthesizers with the Arduino for about 2 years now and have NEVER heard a good filter programmed with it.

Anyway I was wondering if it is possible to process analogRead values with the filter or with delayFeedback?

In other words, does the Arduino have enough processing power to do so? And what commands should I use within the structure of Mozzi?


In my normal C programming experience, I would assign the analogRead to a value. the value would then be processed by a function. the function would then spit
out a value which would be sent to an output.

however, Mozzi is set up much differently (especially for someone used to C)

So I suppose this is a a question both about processing audio and also how to properly call the filter or delay function.


THANKS SO MUCH FOR ALL YOUR HARD WORK!

dan

Mr Sensorium

unread,
Mar 18, 2013, 6:45:12 AM3/18/13
to mozzi...@googlegroups.com
Hi Dan,


>possible to process analogRead values with the filter or with delayFeedback?
>does the Arduino have enough processing power to do so?

I haven't got around to it yet, but here's a couple of examples showing that it can be done:

http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/
http://www.instructables.com/id/Arduino-Vocal-Effects-Box/

I just need time to add it...aaahgh
falling down a hole sound

Tim

loss1234

unread,
Mar 18, 2013, 9:08:00 AM3/18/13
to mozzi...@googlegroups.com
I think you misunderstood my question...sorry...

I know how to process audio with Arduino. I have done it many, many times. BUT always in the context of programs that just use

void setup

void loop.

Since MOZZI is  using many behind the scenes .h and .cpp files, I am not sure if you have such a feature enabled, or
where in the program I would place my calls to analaogRead.


I will try a program today and see if I can get anything working. I am sure I will have questions.


thanks for your help



Mr Sensorium

unread,
Mar 18, 2013, 9:56:42 AM3/18/13
to mozzi...@googlegroups.com
Dan,

At the moment, Mozzi doesn't have a convenient wrapper for continuous audio rate ADC, but it does have 2 different ways to do asynchronous ADC.

For an audio in, I would recommend putting setupFastAnalogRead() in setup(), which reduces the timing of a reliable read from 105us to 15us.  You might need startAnalogRead(unsigned char pin) in the setup too, to get it going.

Then in updateAudio() you can use receiveAnalogRead() to get the most recent value, followed by startAnalogRead(unsigned char pin) which will set the next read happening in the background.  I think it would work best to put both of these at the beginning of updateAudio(), so the next ADC can happen while your audio code runs.

At 16384Hz, there is (at most) 61us between each updateAudio() if the audio output buffer is full, so there's time for the 15us ADC conversion to occur between calls.  I haven't tried it at audio rate myself yet, so I would be keen to know if it works or if there are any hitches.

Actually recieving the analog in takes about 1us, and the StateVariable and LowPassFilter take about 14 and 16 us respectively for each sample.  The current version of AudioDelayFeedback takes 18us, but in the upcoming version it is much faster at 4us, and the LowPassFilter is also improved to 10us.
So there should be time to do some processing of the input samples.

There are examples and documentation for all these in the download if you are wondering how to call them properly as you asked in your earlier message (although I seem to have got rid of the example showing that particular way of reading analog.  I'll include one again in the next release).  Let me know if it's unclear or where the documentation needs improving.

Tim

loss1234

unread,
Mar 20, 2013, 4:26:04 PM3/20/13
to mozzi...@googlegroups.com

well I think in some ways I am more confused now with the addition of the startAnalogRead and ReceiveAnalogRead commands.

I am just not sure where they go in relation to the setup of pins at the top of the sketch and where they go in setupAudio in relation to the
calls to get the audio into the filter.

anyway......here is what I got togther. it does not work at this stage.

actually it seemed to work a bit better before I put in the fast analog read stuff BUT probrably only because I am putting stuff in incorrectly.


BUT this is a start to hopefully get a conversation going!

thanks

CODE BELOW


Dan




/*  Example of using analog pots, and an analog input with filter
 *  using Mozzi sonification library.
 *

 *
 *  Circuit: Audio output on digital pin 9 (on a Uno or similar), or
 *  check the README or http://sensorium.github.com/Mozzi/
 *
 *  Mozzi help/discussion/announcements:
 *  https://groups.google.com/forum/#!forum/mozzi-users

 */

#include <MozziGuts.h>
#include <Oscil.h>
#include <tables/triangle_analogue512_int8.h> // wavetable
#include <tables/cos2048_int8.h> // for filter modulation
#include <tables/cos8192_int8.h> // wavetable
#include <AudioDelayFeedback.h>
#include <mozzi_analog.h>
#include <LowPassFilter.h>
#include <mozzi_analog.h>
#include <fixedMath.h> // for fractional modulation frequency

#define CONTROL_RATE 64 // powers of 2 please
unsigned char Audio;  //this is where we will store our audio data

Oscil<COS2048_NUM_CELLS, CONTROL_RATE> kFilterMod(COS2048_DATA);
LowPassFilter lpf;

// Don't use the Arduino A0, A1 etc pin notation, just say 0, 1, 2...
#define CENTRE_FREQ_ANALOG_IN 0
#define MOD_SPEED_ANALOG_IN 1
#define MOD_WIDTH_ANALOG_IN 2
#define AUDIO_IN 3

void setup(){
  startMozzi(CONTROL_RATE);
  lpf.setResonance(200);
 // initADC();
  setupFastAnalogRead();
  startAnalogRead( 3);
}



void updateControl(){
 
  receiveAnalogRead();
  startAnalogRead( 3) ;
  unsigned char centre_freq = (unsigned char) (getSensor(CENTRE_FREQ_ANALOG_IN)>>2); // 0 to 255
  Audio= (unsigned char) (getSensor(AUDIO_IN)>>3); //divide the 0-1023 down to a usable range
 
  Q16n16 modulation_speed = ((Q16n16)getSensor(MOD_SPEED_ANALOG_IN)<<10); // range 0 to 15, Q16n16 fractional
  kFilterMod.setFreq_Q16n16(modulation_speed);

  unsigned char modulation_width = (unsigned char) (getSensor(MOD_WIDTH_ANALOG_IN)>>4); // 0 to 63
  char modulation = ((int) kFilterMod.next() * modulation_width)>>8; // -32 to 31

  // add centre_freq to modulation, and constrain into the filter range (0-255)
  unsigned char cutoff_freq = constrain(centre_freq + modulation, 0, 255);

  lpf.setCutoffFreq(cutoff_freq);

  startRead();
 
}

int updateAudio(){
   char asig = lpf.next(Audio); 
  return (int) asig;
}

void loop(){
  audioHook();
}


loss1234

unread,
Mar 20, 2013, 4:30:13 PM3/20/13
to mozzi...@googlegroups.com
by the way...I could not find any example sketches that use the startAnalogRead and ReceiveAnalogRead....the sketch MOST similar in the examples was the Filter with SENSOR control....but that was still quite a bit different.

really all I think I should have to do is get the audio setup properly, create a variable to "store" the audio in, and then have the filter library interact with that variable.

however since the filter usually interacts like this:

char asig = lpf.next(aCrunchySound.next());

I am not sure if I can just drop a variable in place of the aCrunchySound.next() area or not


thanks

Mr Sensorium

unread,
Mar 21, 2013, 7:36:42 AM3/21/13
to mozzi...@googlegroups.com
Hi Dan,
well I tried a naive approach and it sounds like no go but I've only tried it with a headphone-out from an mp3 player as input so that probably doesn't help.  The level sounds too low, maybe the signal input needs biasing and preamp/buffer or something.
Anyway, it's clear from looking at those 2 links in my earlier post that it's going to be more complicated than I expected, at least if the requirement is to have analog control and audio input at the same time.  Martin Nawrath's example alternates between reading audio and control analog inputs, at twice the audio rate.  Amanda Gassi's example uses external RC circuits and counting on digital-ins for controls, which could cause glitches for Mozzi while it waits.  However, either approach may offer a way forward after some experimentation to see how it could work in with the library.
If anyone has any ideas about this it would be great to hear them.

Here's the sketch which didn't seem too good, if anyone has a better input source to test it with.
#include <MozziGuts.h>
#include <mozzi_analog.h>



#define CONTROL_RATE 64 // powers of 2 please
#define AUDIO_PIN 0


void setup(){
  pinMode
(AUDIO_PIN,INPUT);
  setupFastAnalogRead
();
  startMozzi
(CONTROL_RATE);
}


void updateControl(){
}


int updateAudio(){
 
int asig = (receiveAnalogRead()>>2) - AUDIO_BIAS; // may not need >>2, depending on input level
  startAnalogRead
(AUDIO_PIN);
 
return asig;
}


void loop(){
  audioHook
();
}



TIm

loss1234

unread,
Mar 21, 2013, 9:37:50 AM3/21/13
to mozzi...@googlegroups.com
actually this isnt bad

i removed the analog bias as i didnt have one setup on my inputs (i just chop off anything that goes above 5volts)

(i am plugging in synthesziers)

keep in mind PLEASE that both examples you gave me from other sites are some of the most complicated ways to get audio out an arduino

YES, the vocal processor is high quality, but it only allows for one chanell!

there are other ways


even just using the standard analogRead and PWM Out can give pretty give throughput if done with the right register calls before the sketch



but alas...it might not be possible with all the mozzi libraries as well.


i was SO excited about the prospect of using your filter with incoming audio BUT maybe its not possible.

i will keep working on it


in the meantime I have been getting exciting results with other aspects of Mozzi

thanks

loss1234

unread,
Mar 21, 2013, 9:58:11 AM3/21/13
to mozzi...@googlegroups.com
this is about the best i can get it to read right now.

pretty good (especially with an R2R dac)

but its not quite as good as if you remove MozziGuts.h

so Mozzi is slowing things down somehow


I am now going to try and throw the filter code in between this



#include <MozziGuts.h>
#include <mozzi_analog.h>
const int pinOffset = 5;       // the first DAC pin (from 5-12)



// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


#define CONTROL_RATE 64 // powers of 2 please
#define AUDIO_PIN 2


void setup(){
   // set up the 8-bit DAC output pins
  for (int i=0; i<8; i++) {
   pinMode(pinOffset+i, OUTPUT);
    digitalWrite(pinOffset+i, LOW);
}

 
  // set the ADC to a higher prescale factor
  sbi(ADCSRA,ADPS2);
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);

 
  pinMode(AUDIO_PIN,INPUT);
  setupFastAnalogRead();
  startMozzi(CONTROL_RATE);
}




void updateControl() {
  // your control code
}

int updateAudio() {
  // your audio code which returns an int between -244 and 243
  // actually, a char is fine
  return 0;
}


void loop(){
   int asig = (receiveAnalogRead()>>2); // may not need >>2, depending on input level
  startAnalogRead(AUDIO_PIN);
  dacOutput(asig);
}


void dacOutput(long v)
{
 int tmpVal = v;
 bitWrite(PORTD, 5, tmpVal & 1);
 bitWrite(PORTD, 6, (tmpVal & 2) > 0);
 bitWrite(PORTD, 7, (tmpVal & 4) > 0);
 bitWrite(PORTB, 0, (tmpVal & 8) > 0);
 bitWrite(PORTB, 1, (tmpVal & 16) > 0);
 bitWrite(PORTB, 2, (tmpVal & 32) > 0);
 bitWrite(PORTB, 3, (tmpVal & 64) > 0);
 bitWrite(PORTB, 4, (tmpVal & 128) > 0);
}

Reply all
Reply to author
Forward
0 new messages