Konuyu Oyla:
  • Toplam: 0 Oy - Ortalama: 0
Share Thread:
Raspberry Frekans Üretme
#1
Merhabalar herkese,bir projemiz için raspberry kullanarak belirli frekanslarda ses üretmemiz lazım,bu konuda yardımcı olabilir misiniz ? ya da şöyle mi demeliydim pwm çıkışını kullanarak sinyal üretmek? 
Şimdiden teşekkür ederim
Ara
Cevapla
#2
https://www.raspberrypi.org/forums/viewt...hp?t=56748

Şurada hem test programı hem de C ile yazılmış linklenmiş örnek kod var. Bu linklediğim sayfadaki çözümler faydalı olacaktır.

Referans olsun diye buraya da aktarmak istedim:


http://www.alsa-project.org/alsa-doc/als...ample.html

Kod:
/*
*  This small demo sends a simple sinusoidal wave to your speakers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include "../include/asoundlib.h"
#include <sys/time.h>
#include <math.h>
static char *device = "plughw:0,0";                     /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;    /* sample format */
static unsigned int rate = 44100;                       /* stream rate */
static unsigned int channels = 1;                       /* count of channels */
static unsigned int buffer_time = 500000;               /* ring buffer length in us */
static unsigned int period_time = 100000;               /* period time in us */
static double freq = 440;                               /* sinusoidal wave frequency in Hz */
static int verbose = 0;                                 /* verbose flag */
static int resample = 1;                                /* enable alsa-lib resampling */
static int period_event = 0;                            /* produce poll event after each period */
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
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);
       /* 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...\n", chn, areas[chn].first);
                       exit(EXIT_FAILURE);
               }
               samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
               if ((areas[chn].step % 16) != 0) {
                       printf("areas[%i].step == %i, aborting...\n", 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 = sin(phase);
                       res = fval.i;
               } else
                       res = 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;
}
static int set_hwparams(snd_pcm_t *handle,
                       snd_pcm_hw_params_t *params,
                       snd_pcm_access_t access)
{
       unsigned int rrate;
       snd_pcm_uframes_t size;
       int err, dir;
       /* choose all parameters */
       err = snd_pcm_hw_params_any(handle, params);
       if (err < 0) {
               printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
               return err;
       }
       /* set hardware resampling */
       err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
       if (err < 0) {
               printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* set the interleaved read/write format */
       err = snd_pcm_hw_params_set_access(handle, params, access);
       if (err < 0) {
               printf("Access type not available for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* set the sample format */
       err = snd_pcm_hw_params_set_format(handle, params, format);
       if (err < 0) {
               printf("Sample format not available for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* set the count of channels */
       err = snd_pcm_hw_params_set_channels(handle, params, channels);
       if (err < 0) {
               printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
               return err;
       }
       /* set the stream rate */
       rrate = rate;
       err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
       if (err < 0) {
               printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
               return err;
       }
       if (rrate != rate) {
               printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
               return -EINVAL;
       }
       /* set the buffer time */
       err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
       if (err < 0) {
               printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
               return err;
       }
       err = snd_pcm_hw_params_get_buffer_size(params, &size);
       if (err < 0) {
               printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
               return err;
       }
       buffer_size = size;
       /* set the period time */
       err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
       if (err < 0) {
               printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
               return err;
       }
       err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
       if (err < 0) {
               printf("Unable to get period size for playback: %s\n", snd_strerror(err));
               return err;
       }
       period_size = size;
       /* write the parameters to device */
       err = snd_pcm_hw_params(handle, params);
       if (err < 0) {
               printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
               return err;
       }
       return 0;
}
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
{
       int err;
       /* get the current swparams */
       err = snd_pcm_sw_params_current(handle, swparams);
       if (err < 0) {
               printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* start the transfer when the buffer is almost full: */
       /* (buffer_size / avail_min) * avail_min */
       err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
       if (err < 0) {
               printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* allow the transfer when at least period_size samples can be processed */
       /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
       err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
       if (err < 0) {
               printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
               return err;
       }
       /* enable period events when requested */
       if (period_event) {
               err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
               if (err < 0) {
                       printf("Unable to set period event: %s\n", snd_strerror(err));
                       return err;
               }
       }
       /* write the parameters to the playback device */
       err = snd_pcm_sw_params(handle, swparams);
       if (err < 0) {
               printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
               return err;
       }
       return 0;
}
/*
*   Underrun and suspend recovery
*/

static int xrun_recovery(snd_pcm_t *handle, int err)
{
       if (verbose)
               printf("stream recovery\n");
       if (err == -EPIPE) {    /* under-run */
               err = snd_pcm_prepare(handle);
               if (err < 0)
                       printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
               return 0;
       } else if (err == -ESTRPIPE) {
               while ((err = snd_pcm_resume(handle)) == -EAGAIN)
                       sleep(1);       /* wait until the suspend flag is released */
               if (err < 0) {
                       err = snd_pcm_prepare(handle);
                       if (err < 0)
                               printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
               }
               return 0;
       }
       return err;
}
/*
*   Transfer method - write only
*/
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\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               break;  /* skip one period */
                       }
                       ptr += err * channels;
                       cptr -= err;
               }
       }
}

/*
*   Transfer method - write and wait for room in buffer using poll
*/
static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, unsigned int count)
{
       unsigned short revents;
       while (1) {
               poll(ufds, count, -1);
               snd_pcm_poll_descriptors_revents(handle, ufds, count, &revents);
               if (revents & POLLERR)
                       return -EIO;
               if (revents & POLLOUT)
                       return 0;
       }
}
static int write_and_poll_loop(snd_pcm_t *handle,
                              signed short *samples,
                              snd_pcm_channel_area_t *areas)
{
       struct pollfd *ufds;
       double phase = 0;
       signed short *ptr;
       int err, count, cptr, init;
       count = snd_pcm_poll_descriptors_count (handle);
       if (count <= 0) {
               printf("Invalid poll descriptors count\n");
               return count;
       }
       ufds = malloc(sizeof(struct pollfd) * count);
       if (ufds == NULL) {
               printf("No enough memory\n");
               return -ENOMEM;
       }
       if ((err = snd_pcm_poll_descriptors(handle, ufds, count)) < 0) {
               printf("Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
               return err;
       }
       init = 1;
       while (1) {
               if (!init) {
                       err = wait_for_poll(handle, ufds, count);
                       if (err < 0) {
                               if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN ||
                                   snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) {
                                       err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                       if (xrun_recovery(handle, err) < 0) {
                                               printf("Write error: %s\n", snd_strerror(err));
                                               exit(EXIT_FAILURE);
                                       }
                                       init = 1;
                               } else {
                                       printf("Wait for poll failed\n");
                                       return err;
                               }
                       }
               }
               generate_sine(areas, 0, period_size, &phase);
               ptr = samples;
               cptr = period_size;
               while (cptr > 0) {
                       err = snd_pcm_writei(handle, ptr, cptr);
                       if (err < 0) {
                               if (xrun_recovery(handle, err) < 0) {
                                       printf("Write error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               init = 1;
                               break;  /* skip one period */
                       }
                       if (snd_pcm_state(handle) == SND_PCM_STATE_RUNNING)
                               init = 0;
                       ptr += err * channels;
                       cptr -= err;
                       if (cptr == 0)
                               break;
                       /* it is possible, that the initial buffer cannot store */
                       /* all data from the last period, so wait awhile */
                       err = wait_for_poll(handle, ufds, count);
                       if (err < 0) {
                               if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN ||
                                   snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) {
                                       err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                       if (xrun_recovery(handle, err) < 0) {
                                               printf("Write error: %s\n", snd_strerror(err));
                                               exit(EXIT_FAILURE);
                                       }
                                       init = 1;
                               } else {
                                       printf("Wait for poll failed\n");
                                       return err;
                               }
                       }
               }
       }
}
/*
*   Transfer method - asynchronous notification
*/
struct async_private_data {
       signed short *samples;
       snd_pcm_channel_area_t *areas;
       double phase;
};
static void async_callback(snd_async_handler_t *ahandler)
{
       snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
       struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
       signed short *samples = data->samples;
       snd_pcm_channel_area_t *areas = data->areas;
       snd_pcm_sframes_t avail;
       int err;
       
       avail = snd_pcm_avail_update(handle);
       while (avail >= period_size) {
               generate_sine(areas, 0, period_size, &data->phase);
               err = snd_pcm_writei(handle, samples, period_size);
               if (err < 0) {
                       printf("Write error: %s\n", snd_strerror(err));
                       exit(EXIT_FAILURE);
               }
               if (err != period_size) {
                       printf("Write error: written %i expected %li\n", err, period_size);
                       exit(EXIT_FAILURE);
               }
               avail = snd_pcm_avail_update(handle);
       }
}
static int async_loop(snd_pcm_t *handle,
                     signed short *samples,
                     snd_pcm_channel_area_t *areas)
{
       struct async_private_data data;
       snd_async_handler_t *ahandler;
       int err, count;
       data.samples = samples;
       data.areas = areas;
       data.phase = 0;
       err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, &data);
       if (err < 0) {
               printf("Unable to register async handler\n");
               exit(EXIT_FAILURE);
       }
       for (count = 0; count < 2; count++) {
               generate_sine(areas, 0, period_size, &data.phase);
               err = snd_pcm_writei(handle, samples, period_size);
               if (err < 0) {
                       printf("Initial write error: %s\n", snd_strerror(err));
                       exit(EXIT_FAILURE);
               }
               if (err != period_size) {
                       printf("Initial write error: written %i expected %li\n", err, period_size);
                       exit(EXIT_FAILURE);
               }
       }
       if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) {
               err = snd_pcm_start(handle);
               if (err < 0) {
                       printf("Start error: %s\n", snd_strerror(err));
                       exit(EXIT_FAILURE);
               }
       }
       /* because all other work is done in the signal handler,
          suspend the process */
       while (1) {
               sleep(1);
       }
}
/*
*   Transfer method - asynchronous notification + direct write
*/
static void async_direct_callback(snd_async_handler_t *ahandler)
{
       snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
       struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
       const snd_pcm_channel_area_t *my_areas;
       snd_pcm_uframes_t offset, frames, size;
       snd_pcm_sframes_t avail, commitres;
       snd_pcm_state_t state;
       int first = 0, err;
       
       while (1) {
               state = snd_pcm_state(handle);
               if (state == SND_PCM_STATE_XRUN) {
                       err = xrun_recovery(handle, -EPIPE);
                       if (err < 0) {
                               printf("XRUN recovery failed: %s\n", snd_strerror(err));
                               exit(EXIT_FAILURE);
                       }
                       first = 1;
               } else if (state == SND_PCM_STATE_SUSPENDED) {
                       err = xrun_recovery(handle, -ESTRPIPE);
                       if (err < 0) {
                               printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
                               exit(EXIT_FAILURE);
                       }
               }
               avail = snd_pcm_avail_update(handle);
               if (avail < 0) {
                       err = xrun_recovery(handle, avail);
                       if (err < 0) {
                               printf("avail update failed: %s\n", snd_strerror(err));
                               exit(EXIT_FAILURE);
                       }
                       first = 1;
                       continue;
               }
               if (avail < period_size) {
                       if (first) {
                               first = 0;
                               err = snd_pcm_start(handle);
                               if (err < 0) {
                                       printf("Start error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                       } else {
                               break;
                       }
                       continue;
               }
               size = period_size;
               while (size > 0) {
                       frames = size;
                       err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                       if (err < 0) {
                               if ((err = xrun_recovery(handle, err)) < 0) {
                                       printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               first = 1;
                       }
                       generate_sine(my_areas, offset, frames, &data->phase);
                       commitres = snd_pcm_mmap_commit(handle, offset, frames);
                       if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                               if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                       printf("MMAP commit error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               first = 1;
                       }
                       size -= frames;
               }
       }
}
static int async_direct_loop(snd_pcm_t *handle,
                            signed short *samples ATTRIBUTE_UNUSED,
                            snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
{
       struct async_private_data data;
       snd_async_handler_t *ahandler;
       const snd_pcm_channel_area_t *my_areas;
       snd_pcm_uframes_t offset, frames, size;
       snd_pcm_sframes_t commitres;
       int err, count;
       data.samples = NULL;    /* we do not require the global sample area for direct write */
       data.areas = NULL;      /* we do not require the global areas for direct write */
       data.phase = 0;
       err = snd_async_add_pcm_handler(&ahandler, handle, async_direct_callback, &data);
       if (err < 0) {
               printf("Unable to register async handler\n");
               exit(EXIT_FAILURE);
       }
       for (count = 0; count < 2; count++) {
               size = period_size;
               while (size > 0) {
                       frames = size;
                       err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                       if (err < 0) {
                               if ((err = xrun_recovery(handle, err)) < 0) {
                                       printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                       }
                       generate_sine(my_areas, offset, frames, &data.phase);
                       commitres = snd_pcm_mmap_commit(handle, offset, frames);
                       if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                               if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                       printf("MMAP commit error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                       }
                       size -= frames;
               }
       }
       err = snd_pcm_start(handle);
       if (err < 0) {
               printf("Start error: %s\n", snd_strerror(err));
               exit(EXIT_FAILURE);
       }
       /* because all other work is done in the signal handler,
          suspend the process */
       while (1) {
               sleep(1);
       }
}
/*
*   Transfer method - direct write only
*/
static int direct_loop(snd_pcm_t *handle,
                      signed short *samples ATTRIBUTE_UNUSED,
                      snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
{
       double phase = 0;
       const snd_pcm_channel_area_t *my_areas;
       snd_pcm_uframes_t offset, frames, size;
       snd_pcm_sframes_t avail, commitres;
       snd_pcm_state_t state;
       int err, first = 1;
       while (1) {
               state = snd_pcm_state(handle);
               if (state == SND_PCM_STATE_XRUN) {
                       err = xrun_recovery(handle, -EPIPE);
                       if (err < 0) {
                               printf("XRUN recovery failed: %s\n", snd_strerror(err));
                               return err;
                       }
                       first = 1;
               } else if (state == SND_PCM_STATE_SUSPENDED) {
                       err = xrun_recovery(handle, -ESTRPIPE);
                       if (err < 0) {
                               printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
                               return err;
                       }
               }
               avail = snd_pcm_avail_update(handle);
               if (avail < 0) {
                       err = xrun_recovery(handle, avail);
                       if (err < 0) {
                               printf("avail update failed: %s\n", snd_strerror(err));
                               return err;
                       }
                       first = 1;
                       continue;
               }
               if (avail < period_size) {
                       if (first) {
                               first = 0;
                               err = snd_pcm_start(handle);
                               if (err < 0) {
                                       printf("Start error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                       } else {
                               err = snd_pcm_wait(handle, -1);
                               if (err < 0) {
                                       if ((err = xrun_recovery(handle, err)) < 0) {
                                               printf("snd_pcm_wait error: %s\n", snd_strerror(err));
                                               exit(EXIT_FAILURE);
                                       }
                                       first = 1;
                               }
                       }
                       continue;
               }
               size = period_size;
               while (size > 0) {
                       frames = size;
                       err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                       if (err < 0) {
                               if ((err = xrun_recovery(handle, err)) < 0) {
                                       printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               first = 1;
                       }
                       generate_sine(my_areas, offset, frames, &phase);
                       commitres = snd_pcm_mmap_commit(handle, offset, frames);
                       if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                               if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                       printf("MMAP commit error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               first = 1;
                       }
                       size -= frames;
               }
       }
}

/*
*   Transfer method - direct write only using mmap_write functions
*/
static int direct_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_mmap_writei(handle, ptr, cptr);
                       if (err == -EAGAIN)
                               continue;
                       if (err < 0) {
                               if (xrun_recovery(handle, err) < 0) {
                                       printf("Write error: %s\n", snd_strerror(err));
                                       exit(EXIT_FAILURE);
                               }
                               break;  /* skip one period */
                       }
                       ptr += err * channels;
                       cptr -= err;
               }
       }
}

/*
*
*/
struct transfer_method {
       const char *name;
       snd_pcm_access_t access;
       int (*transfer_loop)(snd_pcm_t *handle,
                            signed short *samples,
                            snd_pcm_channel_area_t *areas);
};
static struct transfer_method transfer_methods[] = {
       { "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop },
       { "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, write_and_poll_loop },
       { "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop },
       { "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, async_direct_loop },
       { "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_loop },
       { "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, direct_loop },
       { "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_write_loop },
       { NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL }
};
static void help(void)
{
       int k;
       printf(
"Usage: pcm [OPTION]... [FILE]...\n"
"-h,--help      help\n"
"-D,--device    playback device\n"
"-r,--rate      stream rate in Hz\n"
"-c,--channels  count of channels in stream\n"
"-f,--frequency sine wave frequency in Hz\n"
"-b,--buffer    ring buffer size in us\n"
"-p,--period    period size in us\n"
"-m,--method    transfer method\n"
"-o,--format    sample format\n"
"-v,--verbose   show the PCM setup parameters\n"
"-n,--noresample  do not resample\n"
"-e,--pevent    enable poll event after each period\n"
"\n");
       printf("Recognized sample formats are:");
       for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
               const char *s = snd_pcm_format_name(k);
               if (s)
                       printf(" %s", s);
       }
       printf("\n");
       printf("Recognized transfer methods are:");
       for (k = 0; transfer_methods[k].name; k++)
               printf(" %s", transfer_methods[k].name);
       printf("\n");
}
int main(int argc, char *argv[])
{
       struct option long_option[] =
       {
               {"help", 0, NULL, 'h'},
               {"device", 1, NULL, 'D'},
               {"rate", 1, NULL, 'r'},
               {"channels", 1, NULL, 'c'},
               {"frequency", 1, NULL, 'f'},
               {"buffer", 1, NULL, 'b'},
               {"period", 1, NULL, 'p'},
               {"method", 1, NULL, 'm'},
               {"format", 1, NULL, 'o'},
               {"verbose", 1, NULL, 'v'},
               {"noresample", 1, NULL, 'n'},
               {"pevent", 1, NULL, 'e'},
               {NULL, 0, NULL, 0},
       };
       snd_pcm_t *handle;
       int err, morehelp;
       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);
       morehelp = 0;
       while (1) {
               int c;
               if ((c = getopt_long(argc, argv, "hD:r:c:f:b:p:m:o:vne", long_option, NULL)) < 0)
                       break;
               switch (c) {
               case 'h':
                       morehelp++;
                       break;
               case 'D':
                       device = strdup(optarg);
                       break;
               case 'r':
                       rate = atoi(optarg);
                       rate = rate < 4000 ? 4000 : rate;
                       rate = rate > 196000 ? 196000 : rate;
                       break;
               case 'c':
                       channels = atoi(optarg);
                       channels = channels < 1 ? 1 : channels;
                       channels = channels > 1024 ? 1024 : channels;
                       break;
               case 'f':
                       freq = atoi(optarg);
                       freq = freq < 50 ? 50 : freq;
                       freq = freq > 5000 ? 5000 : freq;
                       break;
               case 'b':
                       buffer_time = atoi(optarg);
                       buffer_time = buffer_time < 1000 ? 1000 : buffer_time;
                       buffer_time = buffer_time > 1000000 ? 1000000 : buffer_time;
                       break;
               case 'p':
                       period_time = atoi(optarg);
                       period_time = period_time < 1000 ? 1000 : period_time;
                       period_time = period_time > 1000000 ? 1000000 : period_time;
                       break;
               case 'm':
                       for (method = 0; transfer_methods[method].name; method++)
                                       if (!strcasecmp(transfer_methods[method].name, optarg))
                                       break;
                       if (transfer_methods[method].name == NULL)
                               method = 0;
                       break;
               case 'o':
                       for (format = 0; format < SND_PCM_FORMAT_LAST; format++) {
                               const char *format_name = snd_pcm_format_name(format);
                               if (format_name)
                                       if (!strcasecmp(format_name, optarg))
                                       break;
                       }
                       if (format == SND_PCM_FORMAT_LAST)
                               format = SND_PCM_FORMAT_S16;
                       if (!snd_pcm_format_linear(format) &&
                           !(format == SND_PCM_FORMAT_FLOAT_LE ||
                             format == SND_PCM_FORMAT_FLOAT_BE)) {
                               printf("Invalid (non-linear/float) format %s\n",
                                      optarg);
                               return 1;
                       }
                       break;
               case 'v':
                       verbose = 1;
                       break;
               case 'n':
                       resample = 0;
                       break;
               case 'e':
                       period_event = 1;
                       break;
               }
       }
       if (morehelp) {
               help();
               return 0;
       }
       err = snd_output_stdio_attach(&output, stdout, 0);
       if (err < 0) {
               printf("Output failed: %s\n", snd_strerror(err));
               return 0;
       }
       printf("Playback device is %s\n", device);
       printf("Stream parameters are %iHz, %s, %i channels\n", rate, snd_pcm_format_name(format), channels);
       printf("Sine wave rate is %.4fHz\n", freq);
       printf("Using transfer method: %s\n", transfer_methods[method].name);
       if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
               printf("Playback open error: %s\n", snd_strerror(err));
               return 0;
       }
       
       if ((err = set_hwparams(handle, hwparams, transfer_methods[method].access)) < 0) {
               printf("Setting of hwparams failed: %s\n", snd_strerror(err));
               exit(EXIT_FAILURE);
       }
       if ((err = set_swparams(handle, swparams)) < 0) {
               printf("Setting of swparams failed: %s\n", snd_strerror(err));
               exit(EXIT_FAILURE);
       }
       if (verbose > 0)
               snd_pcm_dump(handle, output);
       samples = malloc((period_size * channels * snd_pcm_format_physical_width(format)) / 8);
       if (samples == NULL) {
               printf("No enough memory\n");
               exit(EXIT_FAILURE);
       }
       
       areas = calloc(channels, sizeof(snd_pcm_channel_area_t));
       if (areas == NULL) {
               printf("No enough memory\n");
               exit(EXIT_FAILURE);
       }
       for (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\n", snd_strerror(err));
       free(areas);
       free(samples);
       snd_pcm_close(handle);
       return 0;
}

Veya kuracağınız speaket-test programı ile:

Kod:
speaker-test -t sine -f 440 -c 2 -s 1

440 değerini frekansa göre değiştirirsiniz.

O linkteki tartışmayı incelemenizi öneririm.
Lütfen özel mesajla soru sormayın arkadaşlar. Cevaplamayacağım. Bu forumdaki ben de dahil herkese sorabilecekken neden bir kişiyle yetinesiniz ki?

-Dubito, Ergo Cogito, Ergo Sum
Ara
Cevapla


Hızlı Menü:


Konuyu Okuyanlar: 1 Ziyaretçi