CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Jul 2011
    Posts
    5

    multitone sine 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;
     }

  2. #2
    Join Date
    Jun 2010
    Posts
    115

    Re: multitone sine frequencies

    Long story short, if you are pleased to explain me this function prototype
    static int write_loop(snd_pcm_t *handle,
    signed short *samples,
    snd_pcm_channel_area_t *areas)

    from its use of return type to each definition of its parameters, as well as the details of function scope, I would definitely try to help you finish your project./

  3. #3
    Join Date
    May 2009
    Posts
    2,413

    Re: multitone sine frequencies

    Quote Originally Posted by ogopa View Post
    Any help would be greatly appreciated.
    You just superimpose the two waves. This means you add their amplitudes at each sampling point in time.

  4. #4
    Join Date
    Jul 2011
    Posts
    5

    Re: multitone sine frequencies

    I got the answer. I had to add the two amplitudes as well as two sin(phase).
    Solution: static void generate_multi(snd_pcm_uframes_t offset, int count, double *_phase, double *_phase2)
    {
    static double max_phase = 2. * M_PI;
    double phase = *_phase;
    double phase2 = *_phase2;
    double step = max_phase*freq/(double)rate;
    double step2 = max_phase*freq2/(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 = ampl/8.56;
    float amplitude_scale_2 = ampl2/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) + amplitude_scale_2 * sin(phase2)) * maxval/2;
    res = fval.i;
    } else
    res = (amplitude_scale * sin(phase) + amplitude_scale_2 * sin(phase2)) * maxval/2;
    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;
    phase2 += step2;

    if (phase >= max_phase)
    phase -= max_phase;
    if (phase2 >= max_phase)
    phase2 -= max_phase;
    }
    *_phase = phase;
    *_phase2 = phase2;

    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured