Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

play a waveform at a certain frequency in SDL callback function

I have a waveform 64 samples long. If the sampling rate is 44100 hz, how can I play(loop) this waveform so that it plays arbitrary frequencies?

frequency = samplerate / waveform duration in samples

Therefore the frequency should be 689hz(44100/64). If I wanted it to be say, 65.41hz(C-2), I would have to do this:

65.41 = 44100 / x

Solving for x yields aprox. 674.208. So I need to figure out what speed to play the waveform at to get this frequency. So we can solve this equation:

64 * x = 674.208

and get about 10.5. So the waveform needs to be played at 10.5% of its original speed.

Here is my code:

double smp_index = 0;
double freq = .105;

void callback(void *data, Uint8 *buf, int len){
    int i;
    s8 *out;
    out = (s8*) buf;
    if(smp_index < waveform_length){
        for(i = 0; i < len; i ++){
            out[i] = smpdata[(int)smp_index];
            smp_index +=freq;
            if(smp_index >= waveform_length)
                smp_index = 0;
        }
    }
}

So the resulting audio should be about the note C-2, but its more of a D-2. Is the cast

(int)smp_index

causing the problem? I couldn't see any other way to accomplish this...

like image 668
freedrull Avatar asked Nov 02 '09 23:11

freedrull


1 Answers

Actually, the main problem is not in your code, but in your reasoning.

So we can solve this equation:

64 * x = 674.208

and get about 10.5.

So far so good. (Actually 674.208 should be 674.246 but that's because you rounded 65.41 to 4 significant figures earlier on.)

So the waveform needs to be played at 10.5% of its original speed.

No! The waveform must be slowed down by a factor of 10.5. Which means it must be played at 1/10.5 = 0.095 or 9.5% of its original speed.

like image 181
Artelius Avatar answered Oct 05 '22 04:10

Artelius