X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f
X-Recipient: geda-user AT delorie DOT com
Message-ID: <52C5D542.6040001@buffalo.edu>
Date: Thu, 02 Jan 2014 16:08:18 -0500
From: "Stephen R. Besch"
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.2.0
MIME-Version: 1.0
To: geda-user AT delorie DOT com
Subject: Re: [geda-user] Help sending a sine wave to a speaker
References:
In-Reply-To:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
X-PM-EL-Spam-Prob: X: 10%
Reply-To: geda-user AT delorie DOT com
Rob,
I know that this a few days late, but I do have some ideas - not so much
as to where the error was, since someone already answered this, but in
terms of sine wave generation in general. Basically, I would probably
never use the SIN(x) function directly at all but I would generate the
sine function from a pre-calculated table. This is not as costly as you
might think. In your case, 1KHz at 8KHz sample rate, the table only
requires (worst case) 8 samples, most of which are redundant. These are
Sin(0)=0, Sin(45)=(sqrt2/2), Sin(90)=1, Sin(135)=Sin(45), Sin(180)=0,
Sin(225)=-Sin(45), Sin(270)=-1, Sin(315)=-Sin(45).
In point of fact, there are only 3 unique values(0.0, 1.0, and ~0.707).
The rest are obtained from these by logic and sign inversion. The truth
is that the same is true for higher sampling rates too. Your table only
needs to contain a quarter wave of a 1Hz sine wave. Higher or lower
frequencies can be obtained by changing the rate at which samples are
played back (i.e., play at 8kHz and you get 1KHz, Play at 4kHz and you
get 500Hz, Play at 16KHz and you get 2KHz.
Now, a sine wave sampled at 8f (such as in your case) may look a bit
choppy. But played back through an analog output with a 3db roll off
pole set to some suitable frequency will pull almost the high frequency
edges out of the output and give you an almost perfect sine wave.
Stephen R. Besch
On 12/31/2013 02:26 PM, Rob Butts wrote:
> It has been a while since I've written major C code so I'm having a hard
> time coming up with the code.
> I have a simple design where I use a microchip pic16f1825 to read a byte
> from an eeprom via spi and send it to a dac and ultimately to a speaker.
> As a dac and speaker test I want to send a simple 1000Hz sine wave to the
> dac at an 8KHz rate.
>
> Can anyone check my thoughts below? Here's my thinking...
> If I set my timer to interrupt at an 8KHz rate and if I want to play the
> tone for 10 seconds the for loop might look something like this:
>
> for(j=0; j < 80000; j++){
> // j is the sample index
> // straight sine function means one cycle per 2*pi samples
> // sample(j) = sin(j)
> // multiply by 2*pi now it is one cycle per sample
> // sample(j) = sin((2 * pi) * j)
> // multiply by 1,000 samples per second now it is cycles per second
> // sample(j) = sin(1000 * 2 * pi * j
> // divide by 8000 samples per second now it is cycles per 8000 samples
> // sample(j) = sin(1000 * 2 * pi * j / 8000)
> // the 1000 cycles is the frequency so in those terms
> // sample(j) = sin(freq * 2 * pi * j / 8000)
> // now if I want to normalize the amplitude to 0xff the final value is
> // sample(j) = 0xff * sin(freq * 2 * pi * j / 8000)
> // so... declaring sample as a float
> sample = 0xff * sin(freq * 2 * pi * j / 8000);
> while(!update_dac){ // where update_dac is set to 1 in the timer
> interrupt handler
> }
> update_ dac = 0;
> send_dac((UINT8) sample);
> }
>
> When I execute the code and step through it the value for sample when j = 1
> is 180.238where I expect 3.146
>
> Can someone see my error or what is going on?
>
> Thanks
>
--
fictio cedit veritati