Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/forums/c/)
-   -   multitone sine wave frequencies (http://www.go4expert.com/forums/multitone-sine-wave-frequencies-t26518/)

ogopa 18Aug2011 02:33

multitone sine wave frequencies
 
I have a program that generates a sine wave. I wanted to know how to generate a multitone wave with 2 frequencies using this program.What has to be changed? Any help would be greatly appreciated.

Code:

static void generate_sine(const snd_pcm_channel_area_t *areas,
                          snd_pcm_uframes_t offset,
                          int count, double *_phase)
 {
        static double max_phase = 2. * M_PI;
        double phase = *_phase;
        double step = max_phase*freq/(double)rate;
        unsigned char *samples[channels];
        int steps[channels];
        unsigned int chn;
        int format_bits = snd_pcm_format_width(format);
        unsigned int maxval = (1 << (format_bits - 1)) - 1;
        int bps = format_bits / 8;  // bytes per sample
        int phys_bps = snd_pcm_format_physical_width(format) / 8;
        int big_endian = snd_pcm_format_big_endian(format) == 1;
        int to_unsigned = snd_pcm_format_unsigned(format) == 1;
        int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
                        format == SND_PCM_FORMAT_FLOAT_BE);
    float amplitude_scale = amplitude/8.56;
   
   
    // verify and prepare the contents of areas
        for (chn = 0; chn < channels; chn++) {
                if ((areas[chn].first % 8) != 0) {
                        printf("areas[%i].first == %i, aborting...", chn , areas[chn].first);
                        exit(EXIT_FAILURE);
                }
                samples[chn] = (((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
                if ((areas[chn].step % 16) != 0) {
                        // printf("areas[%i].step == %i, aborting...  ", chn areas[chn].step);
                        exit(EXIT_FAILURE);
                }
                steps[chn] = areas[chn].step / 8;
                samples[chn] += offset * steps[chn];
        }
        // fill the channel areas
        while (count-- > 0) {
                union {
                        float f;
                        int i;
                } fval;
                int res, i;
                if (is_float) {
                        fval.f = amplitude_scale * sin(phase) * maxval;
                        res = fval.i;
                } else
                        res = amplitude_scale * sin(phase) * maxval;
                if (to_unsigned)
                        res ^= 1U << (format_bits - 1);
                for (chn = 0; chn < channels; chn++) {
                        // Generate data in native endian format
                        if (big_endian) {
                                for (i = 0; i < bps; i++)
                                        *(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
                        } else {
                          //      for (i = 0; i < bps; i++)
                        //                *(samples[chn] + i) = (res >>  i * 8) & 0xff;
                        }
                        samples[chn] += steps[chn];
                }
                phase += step;
                if (phase >= max_phase)
                        phase -= max_phase;
        }
        *_phase = phase;
 }

Code:

static int write_loop(snd_pcm_t *handle,
                      signed short *samples,
                      snd_pcm_channel_area_t *areas)
 {
        double phase = 0;
        signed short *ptr;
        int err, cptr;
 
        while (1) {
                generate_sine(areas, 0, period_size, &phase);
        ptr = samples;
                cptr = period_size;
                while (cptr > 0) {
                        err = snd_pcm_writei(handle, ptr, cptr);
                        if (err == -EAGAIN)
                                continue;
                        if (err < 0) {
                                if (xrun_recovery(handle, err) < 0) {
                                        printf("Write error: %s  ", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                break;  /* skip one period */
                        }
                        ptr += err * channels;
                        cptr -= err;
                }
        }
 }




Code:

int main(int argc, char *argv[])
 {
        snd_pcm_t *handle;
        int err;
        snd_pcm_hw_params_t *hwparams;
        snd_pcm_sw_params_t *swparams;
        int method = 0;
        signed short *samples;
        unsigned int chn;
        snd_pcm_channel_area_t *areas;
 
          snd_pcm_hw_params_alloca(&hwparams);
    snd_pcm_sw_params_alloca(&swparams);

    err = snd_output_stdio_attach(&output, stdout, 0);
    printf( "snd_output_stdio_attach err=%d\n", err);
    err = snd_pcm_open(&hspdif, device, SND_PCM_STREAM_PLAYBACK, 0);
    printf( "snd_pcm_open err=%d\n", err);
    err = set_hwparams(hspdif, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    printf( "set_hwparams err=%d\n", err);
    err = set_swparams(hspdif, swparams);
    printf( "set_swparams err=%d\n", err);

    samples = new signed short [period_size * channels * snd_pcm_format_physical_width(format)];
    printf( "samples array_size=%d\n", int( period_size * channels * snd_pcm_format_physical_width(format)) );

    areas = new snd_pcm_channel_area_t [channels];
    printf( "areas channels=%d\n", channels);
    for (unsigned int chn = 0; chn < channels; chn++) {
            areas[chn].addr = samples;
            areas[chn].first = chn * snd_pcm_format_physical_width(format);
            areas[chn].step = channels * snd_pcm_format_physical_width(format);
    }
 
        err = transfer_methods[method].transfer_loop(handle, samples, areas);
        if (err < 0)
                printf("Transfer failed: %s", snd_strerror(err));

        delete [] areas;
        delete []samples;
        snd_pcm_close(handle);
        return 0;
 }


xpi0t0s 18Aug2011 11:47

Re: multitone sine wave frequencies
 
If I read the code correctly then the line where you calculate the data point is this:
Code:

res = amplitude_scale * sin(phase) * maxval;
So it's just a case of doubling up on this, bearing in mind that you may need to reduce the maxval to prevent clipping when peaks reinforce:
Code:

res = (amplitude_scale1 * sin(phase1) + amplitude_scale2 * sin(phase2)) * maxval/2;

ogopa 19Aug2011 19:01

Re: multitone sine wave frequencies
 
Quote:

Originally Posted by xpi0t0s (Post 86144)
If I read the code correctly then the line where you calculate the data point is this:
Code:

res = amplitude_scale * sin(phase) * maxval;
So it's just a case of doubling up on this, bearing in mind that you may need to reduce the maxval to prevent clipping when peaks reinforce:
Code:

res = (amplitude_scale1 * sin(phase1) + amplitude_scale2 * sin(phase2)) * maxval/2;


Thanks alot. That worked perfectly.


All times are GMT +5.5. The time now is 17:03.