sampling analog signals

Hi All,

I built a simple analog sequencer using the CMOS 4017 chip to control a VCO. Each pin of the 4017 is connected to a pot and as I change the values, I often think it’d be cool to hear my knob turns played back at me in order. This is something that is much easier in the digital world, so I decided to hook it up to Arduino.

I can easily just pass the signal through to the VCO with something like this:

sequence = analogRead(signalIn);
analogWrite(audioOut,HIGH*sequence);

However, what I want to do is store the analog signal in a buffer that I can then sequence. Basically, I need to store it in something like an array that holds snippets of continuous analog signal and would start recording the next value when it receives a high or low signal from the reset pin on the 4017. Then I could have it play back each snippet of signal in order to replicate my hands turning the pots.

I’m not really sure how to store a few seconds of analog signal other than having a while loop with a short delay fill an array. However, I don’t believe the Arduino language allows arrays of arrays so I don’t know how to organize the samples separately for each time the 4017 runs through its sequence.

I hope this makes sense…I’m not sure if I’m using the correct terminology for everything. Please let me know if there’s anyway I can clarify.

Thanks,
Zach

However, I don't believe the Arduino language allows arrays of arrays

It does, but unless you add some memory or use a very slow sample rate, you're going to have very short loops. If your samples are 10 bit and you don't pack them, they're going to take up 2 bytes each, and you've only got 1 or 2 K bytes (depends on processor) maximum.

You could use an SD card, and a data logger function to store the data. Then, replay from the SD card.

AWOL, from what you're describing it doesn't seem like memory should be an issue. The samples are likely to be no longer than 3 seconds (to overestimate) and I only need to store 4 or so of them at a time.

Can you possibly link me to some examples of this?

So you need to store about four lots of three seconds of data?

At two bytes per sample, with an optimistic 900 bytes available gives a shade shy of 38 samples per second. Is that enough?

Okay, I think I was confused by your original description. Memory does present a problem.

Can you recommend a technique to compress the samples, since obviously there is not a continuous stream of data. Maybe I can only store the signal only if it's over a certain threshold and just note the length of silence in between?

PaulS, could I use the Wave Shield to store these to an SD card? I imagine they would have a library for that.

The WaveShield provides the hardware. There are several libraries around that support writing to, and reading from, the cards. Which library you want depends on whether you need to create a file or just read and write from an existing file, and whether you want to be able to use the card in other devices.

I would still like to find an algorithm to store this on the chip, as the cost of the Wave shield would exceed everything else in this sequencer I'm building.

Surely there must be simple audio compression algorithms like this?

Here's a simple suggestion: reduce the data acquisition resolution both in analogin value and in sample time. Then store the data as two bytes A & B. A = the analog value B = the number of time intervals the signal stayed at value A

This would be optimized for signals that don't change much.

I think I get what you're driving at Mitch, but it doesn't seem a good solution for analog signals as I'm interested in sampling their full timbre with the attack and delay. It seems like this would basically make them sound much more "digital," no?

Another solution would be instead of sampling the signal out of the 4017, to simply store the value of the pots connected to each pin as a scalar (i.e. only storing it when it changes). Unfortunately, I have had trouble with even this. I can't even correctly route the pot through the Arduino and back to the VCO without processing it at all! Any example code of this would be greatly appreciated.

Thanks, Zach

you're right, mine is not a good suggestion for high fidelity. All I can say is... you're limited. First with how much data you can store on Arduino, and second by how fast you can extract data from Arduino serial.

Surely there must be simple audio compression algorithms like this?

Not that gives you enough compression. You are describing things like delta modulation methods and that does not reduce the sample size enough for the very small amount of memory we have in this controller. also:-

sampling their full timbre with the attack and delay

puts quite a high value on the sample rate you require. If you have 900 bytes to play with (possibly only 800) you can only sample at 800 Hz for one second. That gives you a top frequency of 400Hz in your sample. I am sure this is not enough for you. Compression on the fly will not give you enough savings, it could only potentially give you a X4 reduction of the space.

I can't even correctly route the pot through the Arduino and back to the VCO without processing it at all!

No you can't do this that's why you have failed. You have to take the analogue value reading and convert it into an analogue output possibly with an external D/A.

Grumpy Mike, can you possibly elaborate on the last point? Are you saying I have to use an external dac to send values back to the analog circuit after digital processing? Where would I find such a dac? I had no trouble just passing the mixing bus straight through the Arduino to the preamp.

I had no trouble just passing the mixing bus straight through the Arduino to the preamp

That's the bit I don't understand, what signal were you taking out of the arduino into an analogue system? The arduino can only output digital signals, without a D/A chip I can't see how this is done apart from using PWM and a filter. http://www.thebox.myzen.co.uk/Tutorial/PWM.html

Lots of D/A chips to choose from:- http://uk.farnell.com/jsp/search/browse.jsp?N=500006+1004458&Ntk=gensearch_001&Ntt=D%2FA&Ntx=

I was just using analogWrite out one of the pwm pins, as in the code example in my first post in this thread.

I'm going to have to read through the article about filters and possibly experiment with a dac chip. Can you direct me to any tutorials on this kind of thing (replicating or sampling a pot) specifically for Arduino?

analogWrite(audioOut,HIGH*sequence);

if you do HIGH*sequence then you are multiplying a boolean logic high with an integer value. I am not sure what that will give you but it will not be what you think. At best it will do nothing and you will just have:- analogWrite(audioOut,sequence); at worst it will overwrite your value and give you:- analogWrite(audioOut,HIGH); Either way this is not giving you what you think. Did this actually work? If so I am surprised.

I don't know of any simple examples of adding A/D maybe I should write one. You could start searching here:- http://www.arduino.cc/playground/Main/ArduinoSynth

HIGH and LOW are #defined, with values of 1 and 0, respectively. They are not booleans.

{smacks forehead} One and zero aren't boolean? What have I been thinking of all these years? ;D

if you do HIGH*sequence then you are multiplying a boolean logic high with an integer value. I am not sure what that will give you

If you KNOW that HIGH is 1 and LOW is 0, why don't you know what HIGH*sequence will give?

I just figured multiplying by HIGH would scale the value of the pot to the Arduino's output voltage, but I was likely incorrect.

I realize I should have done much more research on general Arduino audio stuff before posting here. Apologies all around.

However, in everything I've read today, I did not see one option described: what if I were to replace the pots on the 4017 with photoresistors and use an optical gate with LEDs dimmed by pwm, controlled by pots going into Arduino's analog in? I think this may be the winner...