method to generate arbirtrary shaped sound energy

I am trying to generate a special type of noise. Its not pink or white, or another color, it has a specific "spectrum" so to speak. Its basically filtered white noise, but I think it would be too difficult to recreate reliably and cheaply with multiple analog filters. It looks like pink noise from 20 hz to about 700 hz, then it has various peaks and valleys. I would like to make a very inexpensive playback device for this noise sound, based on clocking out a cheap flash memory into an RC filter. The process would go like this:

1) mathematically generate the sound somehow in the analog domain (pure math)

2) take the pure math sound, and generate an appropriate bit stream, designed to recreate the analog sound by playing the bitstream into an RC filter

so what we are doing here is taking an analog domain sound (the pure math) and mathematically transforming it into a bitstream that when played into a simple rc filter will recreate the original analog sound. this is possible right?

I dont know how to do steps 1 or 2. I figure step 1 should be easy to do in C. So since I want a 20khz upper frequency to be reproduced, each second of sound will require 40000 samples, right? So if I want this noise sound to loop every 5 seconds (to keep the size of the flash memory down), I will need 40000 * 5 samples, which is 200,000 samples. So in C, make a 200,000 byte array, and then starting at 20hz, create a sine wave whose amplitude matches the energy of the spectrum of the desired noise at 20 hz, and put it in the array. The move to 20hz + .001hz, and do it again, but mix it with the existing sound in the array, and continue this process until you get to 20,000hz. Then you have a 5 second long array of an analog-domain sound which matches the spectrum of the sound I want to recreate.

Now to play this array back using our flash memory/rc filter setup, we have to take the array, and transform it into a bitstream which when played back on the rc filter, will recreate the original sound (which we are starting with). I suppose you could use some simple closed loop method,

formatting link

Does this make sense?

Could you recreate white noise using this method? And does it matter what phase I start the sine wave at when creating the array?

Reply to
acannell
Loading thread data ...

Yes.

Nothing analog about it. It is a bunch of numbers generated by computer code.

I didn't follow the link. But what you are saying more or less makes sense.

I don't think step 2 is necessary. Once you have the numbers representing voltage, (or SPL, I guess) you have everything you need. These numbers are, in essence, samples of the noise you want to make. Just like the numbers in a .WAV file.

The idea you are talking about above is feeding a pulse-width modulated (PWM) output into an RC filter as a way of converting from digital to analog. Another way is to just send your generated samples to a DAC. This might be easier, if not cheaper.

If you do want to do the PWM thing, the easiest way might be to have a microcontroller with a PWM output read the samples directly from the ROM (Flash or whatever) and load them into the PWM register. Then the PWM output goes to the RC filter.

Making the bitstream into a PWM signal directly (this is your step 2, above) seems like a waste of ROM to me, although it is possible, if you have enough ROM space.

--Mac

Reply to
Mac

Yes.

There is a better way to do that. Design/choose a digital filter (FIR or IIR) whose frequency response matches the desired frequency shape of your noise. Generate white noise (with rnd function) and feed it to your digital filter. The output from the filter is noise with the desired frequency shape.

In your case, since the desired freq shape is not simple, you may need to play with some filter design tool, to manually create the shape you need. Matlab can help you with that. For instance, the pole/zero editor in the signal processing GUI tool (command "sptool") lets you manually create almost any kind of filter. Once you have chosen your filter (vectors "a" and "b." "b" is the numerator of your filter," and "a" is the denominator. If FIR, "a"=1), filtering is as straightforward as executing y=filter(b,a,x); where "x" is your input vector with random values, and "y" your output vector.

Some options:

- The flash stores 8-bit samples, and you use a DAC to convert them into 256-level pulses, which can be easily RC filtered.

- Since you won't find 1-bit wide flash chips, you can use a parallel-to-serial converter to convert the 8-bit output from your flash into a 1-bit stream that can be also RC filtered. You need more math to do this, since you have to design/choose what kind of bitstream you want to use. You don't need a DAC, but you need a parallel-to-serial converter, and some extra glue logic to synchronize them.

- An MCU extracts data from the flash, and generates a PWM (easy) or any other kind of bitstream (can be more complex), that is finally RC filtered. PWM adds distortion, but if you can live with it, it can be a good alternative to the DAC.

If you need a very cheap solution, you can use option one without a DAC. A few resistors and a logic inverter (say 4049UB) with negative feedback can do D-to-A conversion with reasonable quality. I once gave as a present a circuit like this to a friend, with my voice greeting recorded on the (by then) EEPROM.

If you want to generate the noise the way you explained, I believe you would need to give each sine wave a random phase value, including the first one.

Best,

Reply to
Mochuelo

Thanks for your response Mochuelo. I like your idea of using matlab to generate the digital filter and then the actual shaped-spectrum noise directly, so that all I have to do next is work on getting a DAC or filtered PWM running. Might you know of a freeware alternative to Matlab that would accomplish the same thing?

Thanks!

Asa

Reply to
acannell

You can do this, but there are a few things you should consider:

1) You don't need to calculate so many frequencies. You want to cover 20Hz to 20kHz, so you only need multiples of 20 Hz, which is less than 1000 of them.

2) You should either increase your playback rate and the number of samples, or reduce your upper frequency limit to maybe 15 kHz because the 2F Nyquist criterion is only a minimum theoretical value for an infinitely long sample.

3) You must randomize the starting phase of each sine wave or all you'll get is a series of pulses at 20 Hz.

4) You can save a lot of memory if you record just 1 second of noise and loop it. You'll get some pulsation at 1 Hz, but you may be able to choose an optimal looping point that sounds best.

-- Joe Legris

Reply to
jalegris

Thus spake snipped-for-privacy@wwc.com:

What's the end purpose of your endeavour?

--
DaveC
me@privacy.net
This is an invalid return address
Please reply in the news group
Reply to
DaveC

Usse my magic sinewave techniques.

Which routinely use 44,000 bit words to create quite specific "sounds".

formatting link

--
Many thanks,

Don Lancaster                          voice phone: (928)428-4073
Synergetics   3860 West First Street   Box 809 Thatcher, AZ 85552
rss: http://www.tinaja.com/whtnu.xml   email: don@tinaja.com

Please visit my GURU\'s LAIR web site at http://www.tinaja.com
Reply to
Don Lancaster

Thanks for your interesting reply Joe! When I go to iteratively mix each frequency, I add the existing value in the array to the current value right? Not multiply? I.e. the first pass will yield a big array with 20hz in it. The second pass, at 40 hz, should be added to the array or mutplied by the values in the array?

Reply to
acannell

I know that Scilab is somewhat similar to Matlab, but I have never used it.

formatting link

On the other hand, computing the output from your filter is as simple as solving for y(n) in

a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) - a(2)*y(n-1) - ... - a(na+1)*y(n-na),

which is what Matlab does. You can easily do that with any programming language. To design the filter, however, some high-level functions do help. You need to find "b" (if FIR) or "a" and "b" (if IIR) such that your response is as close as possible to the desired one.

Best,

Reply to
Mochuelo

Added, not multiplied.

Of course, each frequency component must first be scaled by the corresponding amplitude of your frequency response function. You should also consider gradually fading in the first decade of frequencies (from

20 Hz to 200 Hz), and fading out the last decade (from 2 kHz to 20 kHz) by a nice smooth "windowing" function to avoid the effects of a sudden change from zero to full power at the ends of your band of frequencies.

What you are actually doing is computing a discrete inverse Fourier transform using phase shifted sine functions instead of the usual complex exponential function. The main difference, as far as you are concerned, is that the complex exponential form expresses the phase as relative proportions of orthogon sine and cosine components. But your system is easier to understand if you don't know complex function theory.

Here's some info:

formatting link

-- Joe Legris

Reply to
jalegris

Octave is a free Matlab clone. Of course it is not as full featured as Matlab, and I don't know if it runs on Windows.

--Mac

Reply to
Mac

Hi Joe,

I tried the inverse discrete FFT method you described, and it worked! Problem is I get wierd warbling at very low frequencies, it sounds like a heartbeat. But I did a spectral analysis of the original and my reproduction and the spectrums are identical, except mine is less smooth especially below 100hz where there are very large peaks and valleys. I though this might be becase I was using a 2.4hz "step" when generating random-phase waveforms. I tried decreasing the step size to

0.1hz, by simply duplicating the amplitude of the previous 2.4hz step until the next step in 0.1hz increments, but I got what appears to be white noise, with a flat spectrum that seems to increase by about 3db per octave and sounds white. I am not sure whats going on now. Perhaps I am not using big enough numbers (I am using 4 byte floating point max 6 significant digits) and 0.1hz differences cant even be put into my array and all the energy is lumping up somehow?

I figured I couldnt use 20hz steps like you suggested because I have a gentle slope from 20hz to 500hz that I dont think could be recreated with such a large step. Am I wrong? How would the energy at say 45hz be recreated? Wouldnt there be big gaps in the spectrum?

Reply to
acannell

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.