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: 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; }
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;