step calculation for sampled sin sample

Calling for a math guru,

would be nice if someone could explain this

I need to find the stepsize to get a nice sin wave

and maybe other waves in the future. but I'm confused

Anyone ?

1void CustomProgram::Tone(int a_nFrequency, int a_nDuration)
2{
3 unsigned int samples = (float(a_nDuration)/1000.0 * a_nFrequency)*100;
4 unsigned long sample_size=al_get_channel_count(ALLEGRO_CHANNEL_CONF_1) *al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
5 unsigned long bytes = samples * sample_size;
6
7 void *buff = NULL;
8 buff = al_malloc(bytes);
9
10 al_destroy_sample(m_pSample);
11 m_pSample = al_create_sample (buff,samples, a_nFrequency,ALLEGRO_AUDIO_DEPTH_INT16,ALLEGRO_CHANNEL_CONF_1,true);
12
13
14 if (m_pSample!=NULL)
15 {
16 int16_t * ptr = (int16_t *) al_get_sample_data(m_pSample);
17 double step = double(2 * PI * a_nDuration * a_nFrequency) / samples; // <----- This one here !
18 for (unsigned int i=0;i<samples;i++)
19 {
20 ptr[i]= sin(i*step) * 30000;
21 }
22 al_play_sample (m_pSample,1.0,0,1.0,ALLEGRO_PLAYMODE_ONCE,NULL);
23 }
24}

You need to have a_nFrequency steps per second for a_nDuration seconds. The desired frequency of sine wave needs to be divided by a_nFrequency steps per second to get the increment to pass to the float that is input to the sin() function.

Let's say that a_nFrequency is 28,000 hertz, duration is 10 seconds, and you want a sin wave to produce concert A (440 hertz).

So you'd need 28,000 * 10 sample elements to put the sin values into, and the increment per sample element would be 440.0/28000.0 .

As Elias pointed out below, I forgot about the 2.0 * M_PI to get one complete cycle from sin().

Well, just look at a sine wave:

y = sin(x)

If x runs from 0 to 2 * pi, you get one complete wave. Now multiply by 2 * pi:

y = sin(x * 2 * pi)

Now the full wave goes from 0 to 1. Now assume x is our time in seconds, and you want a 440 Hz tone:

y = sin(x * 2 * pi * 440);

Now each seconds there is 440 complete sine waves.

Now, instead of having the time in seconds, x is a sample position, 48000 samples make up one second:

y = sin(x * 2 * pi * 440 / 48000);

In your code, a_nFrequency is the 48000. So a_nDuration/samples is your tone's frequency. I'm a bit unsure about those variable names, I'd say you can simplify that function a lot and still have it do the same thing.

Thnx,

I think this is what it should look like.

I'll try to make some effects using harmonics , see what can be done with this.

Allegro 5 should definitely get some "record sample" or "audio input" functions

1void CustomProgram::Tone(int a_nFrequency, int a_nVolume, int a_nDuration)
2{
3 int nSampleRate = 48000;
4 if (a_nVolume > 255)
5 {
6 a_nVolume = 255;
7 }
8 else if (a_nVolume<0)
9 {
10 a_nVolume = 0;
11 }
12
13 int nInternalVolume = (30000 * a_nVolume)/255;
14 unsigned int samples = (nSampleRate * a_nDuration) / 1000.0;
15 unsigned long sample_size=al_get_channel_count(ALLEGRO_CHANNEL_CONF_1) *al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
16 unsigned long bytes = samples * sample_size;
17
18 void *buff = NULL;
19 buff = al_malloc(bytes);
20
21 al_destroy_sample(m_pSample);
22 m_pSample = al_create_sample (buff,samples, nSampleRate ,ALLEGRO_AUDIO_DEPTH_INT16,ALLEGRO_CHANNEL_CONF_1,true);
23 double dFi = double(2 * PI * a_nFrequency) / nSampleRate;
24
25 if (m_pSample!=NULL)
26 {
27 int16_t * ptr = (int16_t *) al_get_sample_data(m_pSample);
28 for (unsigned int i=0;i<samples;i++)
29 {
30 ptr[i]= sin(i * dFi) * nInternalVolume;
31
32 }
33 al_play_sample (m_pSample,1.0,0,1.0,ALLEGRO_PLAYMODE_ONCE,NULL);
34 }
35}

Looks good to me now, assuming a_nDuration is in ms.