static int pcm_open(pcm_handle_t* pcm, const pcm_desc_t* desc) { const snd_pcm_format_t fmt = SND_PCM_FORMAT_S16_LE; snd_pcm_stream_t stm; int err; if (desc->flags & PCM_FLAG_IN) stm = SND_PCM_STREAM_CAPTURE; else stm = SND_PCM_STREAM_PLAYBACK; err = snd_pcm_open (&pcm->pcm, desc->name, stm, SND_PCM_NONBLOCK); if (err) PERROR_GOTO(snd_strerror(err), on_error_0); err = snd_pcm_hw_params_malloc(&pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_1); err = snd_pcm_hw_params_any(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_access (pcm->pcm, pcm->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_format(pcm->pcm, pcm->hw_params, fmt); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_rate (pcm->pcm, pcm->hw_params, desc->fsampl, 0); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); pcm->nchan = desc->nchan; pcm->wchan = (size_t)snd_pcm_format_physical_width(fmt) / 8; pcm->scale = pcm->nchan * pcm->wchan; err = snd_pcm_hw_params_set_channels (pcm->pcm, pcm->hw_params, desc->nchan); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_malloc(&pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_current(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #if 1 err = snd_pcm_sw_params_set_avail_min (pcm->pcm, pcm->sw_params, 1024); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif #if 1 err = snd_pcm_sw_params_set_start_threshold (pcm->pcm, pcm->sw_params, 0U); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif err = snd_pcm_sw_params(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); err = snd_pcm_prepare(pcm->pcm); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); pcm->rpos = 0; pcm->wpos = 0; pcm->nsampl = (size_t)desc->fsampl * 10; pcm->buf = malloc(pcm->nsampl * pcm->scale); if (pcm->buf == NULL) goto on_error_3; return 0; on_error_3: snd_pcm_sw_params_free(pcm->sw_params); on_error_2: snd_pcm_hw_params_free(pcm->hw_params); on_error_1: snd_pcm_close(pcm->pcm); on_error_0: return -1; }
static pj_status_t open_capture (struct alsa_stream* stream, const pjmedia_aud_param *param) { snd_pcm_hw_params_t* params; snd_pcm_format_t format; int result; unsigned int rate; snd_pcm_uframes_t tmp_buf_size; snd_pcm_uframes_t tmp_period_size; if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt) return PJMEDIA_EAUD_INVDEV; /* Open PCM for capture */ PJ_LOG (5,(THIS_FILE, "open_capture: Open capture device '%s'", stream->af->devs[param->rec_id].name)); result = snd_pcm_open (&stream->ca_pcm, stream->af->devs[param->rec_id].name, SND_PCM_STREAM_CAPTURE, 0); if (result < 0) return PJMEDIA_EAUD_SYSERR; /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca (¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any (stream->ca_pcm, params); /* Set interleaved mode */ snd_pcm_hw_params_set_access (stream->ca_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Set format */ switch (param->bits_per_sample) { case 8: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S8")); format = SND_PCM_FORMAT_S8; break; case 16: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE")); format = SND_PCM_FORMAT_S16_LE; break; case 24: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S24_LE")); format = SND_PCM_FORMAT_S24_LE; break; case 32: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S32_LE")); format = SND_PCM_FORMAT_S32_LE; break; default: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE")); format = SND_PCM_FORMAT_S16_LE; break; } snd_pcm_hw_params_set_format (stream->ca_pcm, params, format); /* Set number of channels */ TRACE_((THIS_FILE, "open_capture: set channels: %d", param->channel_count)); snd_pcm_hw_params_set_channels (stream->ca_pcm, params, param->channel_count); /* Set clock rate */ rate = param->clock_rate; TRACE_((THIS_FILE, "open_capture: set clock rate: %d", rate)); snd_pcm_hw_params_set_rate_near (stream->ca_pcm, params, &rate, NULL); TRACE_((THIS_FILE, "open_capture: clock rate set to: %d", rate)); /* Set period size to samples_per_frame frames. */ stream->ca_frames = (snd_pcm_uframes_t) param->samples_per_frame / param->channel_count; TRACE_((THIS_FILE, "open_capture: set period size: %d", stream->ca_frames)); tmp_period_size = stream->ca_frames; snd_pcm_hw_params_set_period_size_near (stream->ca_pcm, params, &tmp_period_size, NULL); TRACE_((THIS_FILE, "open_capture: period size set to: %d", tmp_period_size)); /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) tmp_buf_size = (rate / 1000) * param->input_latency_ms; else tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY; snd_pcm_hw_params_set_buffer_size_near (stream->ca_pcm, params, &tmp_buf_size); stream->param.input_latency_ms = tmp_buf_size / (rate / 1000); /* Set our buffer */ stream->ca_buf_size = stream->ca_frames * param->channel_count * (param->bits_per_sample/8); stream->ca_buf = (char*) pj_pool_alloc (stream->pool, stream->ca_buf_size); TRACE_((THIS_FILE, "open_capture: buffer size set to: %d", (int)tmp_buf_size)); TRACE_((THIS_FILE, "open_capture: capture_latency set to: %d ms", (int)stream->param.input_latency_ms)); /* Activate the parameters */ result = snd_pcm_hw_params (stream->ca_pcm, params); if (result < 0) { snd_pcm_close (stream->ca_pcm); return PJMEDIA_EAUD_SYSERR; } PJ_LOG (5,(THIS_FILE, "Opened device alsa(%s) for capture, sample rate=%d" ", ch=%d, bits=%d, period size=%d frames, latency=%d ms", stream->af->devs[param->rec_id].name, rate, param->channel_count, param->bits_per_sample, stream->ca_frames, (int)stream->param.input_latency_ms)); return PJ_SUCCESS; }
static int set_hwparams (GstAlsaSink * alsa) { guint rrate; gint err; snd_pcm_hw_params_t *params; guint period_time, buffer_time; snd_pcm_hw_params_malloc (¶ms); GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) " "SPDIF (%d)", alsa->channels, alsa->rate, snd_pcm_format_name (alsa->format), alsa->iec958); /* start with requested values, if we cannot configure alsa for those values, * we set these values to -1, which will leave the default alsa values */ buffer_time = alsa->buffer_time; period_time = alsa->period_time; retry: /* choose all parameters */ CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config); /* set the interleaved read/write format */ CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access), wrong_access); /* set the sample format */ if (alsa->iec958) { /* Try to use big endian first else fallback to le and swap bytes */ if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) { alsa->format = SND_PCM_FORMAT_S16_LE; alsa->need_swap = TRUE; GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping"); } else { alsa->need_swap = FALSE; } } CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format), no_sample_format); /* set the count of channels */ CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels), no_channels); /* set the stream rate */ rrate = alsa->rate; CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL), no_rate); if (rrate != alsa->rate) goto rate_match; #ifndef GST_DISABLE_GST_DEBUG /* get and dump some limits */ { guint min, max; snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL); snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL); GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u", alsa->buffer_time, min, max); snd_pcm_hw_params_get_period_time_min (params, &min, NULL); snd_pcm_hw_params_get_period_time_max (params, &max, NULL); GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u", alsa->period_time, min, max); snd_pcm_hw_params_get_periods_min (params, &min, NULL); snd_pcm_hw_params_get_periods_max (params, &max, NULL); GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max); } #endif /* now try to configure the buffer time and period time, if one * of those fail, we fall back to the defaults and emit a warning. */ if (buffer_time != -1 && !alsa->iec958) { /* set the buffer time */ if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params, &buffer_time, NULL)) < 0) { GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set buffer time %i for playback: %s", buffer_time, snd_strerror (err))); /* disable buffer_time the next round */ buffer_time = -1; goto retry; } GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time); } if (period_time != -1 && !alsa->iec958) { /* set the period time */ if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params, &period_time, NULL)) < 0) { GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set period time %i for playback: %s", period_time, snd_strerror (err))); /* disable period_time the next round */ period_time = -1; goto retry; } GST_DEBUG_OBJECT (alsa, "period time %u", period_time); } /* Set buffer size and period size manually for SPDIF */ if (G_UNLIKELY (alsa->iec958)) { snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE; snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE; CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params, &buffer_size), buffer_size); CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params, &period_size, NULL), period_size); } /* write the parameters to device */ CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params); /* now get the configured values */ CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size), buffer_size); CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL), period_size); GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size, alsa->period_size); snd_pcm_hw_params_free (params); return 0; /* ERRORS */ no_config: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Broken configuration for playback: no configurations available: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } wrong_access: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Access type not available for playback: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } no_sample_format: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Sample format not available for playback: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } no_channels: { gchar *msg = NULL; if ((alsa->channels) == 1) msg = g_strdup (_("Could not open device for playback in mono mode.")); if ((alsa->channels) == 2) msg = g_strdup (_("Could not open device for playback in stereo mode.")); if ((alsa->channels) > 2) msg = g_strdup_printf (_ ("Could not open device for playback in %d-channel mode."), alsa->channels); GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg), ("%s", snd_strerror (err))); g_free (msg); snd_pcm_hw_params_free (params); return err; } no_rate: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Rate %iHz not available for playback: %s", alsa->rate, snd_strerror (err))); return err; } rate_match: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err)); snd_pcm_hw_params_free (params); return -EINVAL; } buffer_size: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to get buffer size for playback: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } period_size: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to get period size for playback: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } set_hw_params: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set hw params for playback: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } }
int main() { int fp,ff; unsigned int pcm, tmp, dir; int buff_size; char filename[20] = "123.wav"; long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; snd_pcm_uframes_t frames; char *buff,*ipaddress; int rate, channels, seconds; //printf("aaa\n"); /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr,"unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 8000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle,params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr,"unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buff large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buff = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 50000000 / val; fp=open("123.wav",O_WRONLY); ipaddress = malloc(sizeof(char) * 4); /*printf("\n\tEnter ip : "); scanf("%s",ipaddress);*/ // printf("sending data\n"); for (loops=500000 / val;loops > 0;loops--) { bzero(buff,sizeof(buff)); rc = snd_pcm_readi(handle, buff, frames); write(fp,buff,128); fun(buff,128,filename); // fucntion1(ipaddress,buff,size); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr,"error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } /* rc = write(1, buff, size); if (rc != size) fprintf(stderr,"short write: wrote %d bytes\n", rc); */ } close(fp); //printf("sending data\n"); /* client1 call(222.wav)*/ snd_pcm_drain(handle); snd_pcm_close(handle); free(buff); return 0; }
bool QAudioInputPrivate::open() { #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif clockStamp.restart(); timeStamp.restart(); elapsedTimeOffset = 0; int dir; int err = 0; int count=0; unsigned int freakuency=settings.frequency(); if (!settings.isValid()) { qWarning("QAudioOutput: open error, invalid format."); } else if (settings.sampleRate() <= 0) { qWarning("QAudioOutput: open error, invalid sample rate (%d).", settings.sampleRate()); } else { err = -1; } if (err == 0) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit errorChanged(errorState); return false; } QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) if (devices.size() > 0) dev = QLatin1String(devices.first()); else return false; #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(m_device); #else int idx = 0; char *name; QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData()); while(snd_card_get_name(idx,&name) == 0) { if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } // Step 1: try and open the device while((count < 5) && (err < 0)) { err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); if(err < 0) count++; } if (( err < 0)||(handle == 0)) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return false; } snd_pcm_nonblock( handle, 0 ); // Step 2: Set the desired HW parameters. snd_pcm_hw_params_alloca( &hwparams ); bool fatal = false; QString errMessage; unsigned int chunks = 8; err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_any: err = %1").arg(err); } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_access: err = %1").arg(err); } } if ( !fatal ) { err = setFormat(); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_format: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params: err = %1").arg(err); } } if( err < 0) { qWarning()<<errMessage; errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return false; } snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames); buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames); snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir); period_size = snd_pcm_frames_to_bytes(handle,period_frames); snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); // Step 3: Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle, swparams); snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames); snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames); snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames); snd_pcm_sw_params(handle, swparams); // Step 4: Prepare audio if(audioBuffer == 0) audioBuffer = new char[buffer_size]; snd_pcm_prepare( handle ); snd_pcm_start(handle); // Step 5: Setup timer bytesAvailable = checkBytesReady(); if(pullMode) connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed())); // Step 6: Start audio processing chunks = buffer_size/period_size; timer->start(period_time*chunks/2000); errorState = QAudio::NoError; totalTimeValue = 0; return true; }
static int pcm_open(struct alsa_pcm *alsa, const char *device_name, snd_pcm_stream_t stream, int rate, int buffer_time) { int r, dir; unsigned int p; size_t bytes; snd_pcm_hw_params_t *hw_params; r = snd_pcm_open(&alsa->pcm, device_name, stream, SND_PCM_NONBLOCK); if (!chk("open", r)) return -1; snd_pcm_hw_params_alloca(&hw_params); r = snd_pcm_hw_params_any(alsa->pcm, hw_params); if (!chk("hw_params_any", r)) return -1; r = snd_pcm_hw_params_set_access(alsa->pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (!chk("hw_params_set_access", r)) return -1; r = snd_pcm_hw_params_set_format(alsa->pcm, hw_params, SND_PCM_FORMAT_S16); if (!chk("hw_params_set_format", r)) { fprintf(stderr, "16-bit signed format is not available. " "You may need to use a 'plughw' device.\n"); return -1; } r = snd_pcm_hw_params_set_rate(alsa->pcm, hw_params, rate, 0); if (!chk("hw_params_set_rate", r )) { fprintf(stderr, "%dHz sample rate not available. You may need to use " "a 'plughw' device.\n", rate); return -1; } alsa->rate = rate; r = snd_pcm_hw_params_set_channels(alsa->pcm, hw_params, DEVICE_CHANNELS); if (!chk("hw_params_set_channels", r)) { fprintf(stderr, "%d channel audio not available on this device.\n", DEVICE_CHANNELS); return -1; } p = buffer_time * 1000; /* microseconds */ dir = -1; r = snd_pcm_hw_params_set_buffer_time_near(alsa->pcm, hw_params, &p, &dir); if (!chk("hw_params_set_buffer_time_near", r)) { fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n", buffer_time); return -1; } p = 2; /* double buffering */ dir = 1; r = snd_pcm_hw_params_set_periods_min(alsa->pcm, hw_params, &p, &dir); if (!chk("hw_params_set_periods_min", r)) { fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n", buffer_time); return -1; } r = snd_pcm_hw_params(alsa->pcm, hw_params); if (!chk("hw_params", r)) return -1; r = snd_pcm_hw_params_get_period_size(hw_params, &alsa->period, &dir); if (!chk("get_period_size", r)) return -1; bytes = alsa->period * DEVICE_CHANNELS * sizeof(signed short); alsa->buf = malloc(bytes); if (!alsa->buf) { perror("malloc"); return -1; } /* snd_pcm_readi() returns uninitialised memory on first call, * possibly caused by premature POLLIN. Keep valgrind happy. */ memset(alsa->buf, 0, bytes); return 0; }
int main() { long loops; int rc; int size; snd_pcm_t *rec_handle; snd_pcm_hw_params_t *rec_params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; WAVEHDR wavheader; int total_len = 0; FILE *fp_rec = fopen("rec.wav", "wb"); if(fp_rec==NULL) { return 0; } wav_start_write(fp_rec, &wavheader); /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&rec_handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&rec_params); /* Fill it in with default values. */ snd_pcm_hw_params_any(rec_handle, rec_params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(rec_handle, rec_params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(rec_handle, rec_params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(rec_handle, rec_params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 8000; snd_pcm_hw_params_set_rate_near(rec_handle, rec_params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(rec_handle, rec_params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(rec_handle, rec_params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(rec_params, &frames, &dir); size = frames * 2; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(rec_params, &val, &dir); loops = 2000; while (loops-- > 0) { rc = snd_pcm_readi(rec_handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(rec_handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } rc = fwrite(buffer, 1, size, fp_rec); total_len += size; printf("#\n"); if (rc != size) fprintf(stderr,"short write: wrote %d bytes\n", rc); } wav_stop_write(fp_rec, &wavheader, total_len); snd_pcm_drain(rec_handle); snd_pcm_close(rec_handle); free(buffer); fclose(fp_rec); return 0; }
int sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr ) { unsigned int exact_rate, periods; unsigned int val, n; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_uframes_t avail_min = 0, sound_periodsize, bsize = 0; static int first_init = 1; static int init_running = 0; const char *option; char tmp; int err, dir, nperiods = NUM_FRAMES; float hz; if( init_running ) return 0; init_running = 1; /* select a default device if we weren't explicitly given one */ option = device; while( option && *option ) { tmp = '*'; if( ( err = sscanf( option, " buffer=%i %n%c", &val, &n, &tmp ) > 0 ) && ( tmp == ',' || strlen( option ) == n ) ) { if( val < 1 ) { fprintf( stderr, "Bad value for ALSA buffer size %i, using default\n", val ); } else { bsize = val; } } else if( ( err = sscanf( option, " frames=%i %n%c", &val, &n, &tmp ) > 0 ) && ( tmp == ',' || strlen( option ) == n ) ) { if( val < 1 ) { fprintf( stderr, "Bad value for ALSA buffer size %i frames, using default (%d)\n", val, NUM_FRAMES ); } else { nperiods = val; } } else if( ( err = sscanf( option, " avail=%i %n%c", &val, &n, &tmp ) > 0 ) && ( tmp == ',' || strlen( option ) == n ) ) { if( val < 1 ) { fprintf( stderr, "Bad value for ALSA avail_min size %i frames, using default\n", val ); } else { avail_min = val; } } else if( ( err = sscanf( option, " verbose %n%c", &n, &tmp ) == 1 ) && ( tmp == ',' || strlen( option ) == n ) ) { verb = 1; } else { /* try as device name */ while( isspace(*option) ) option++; if( *option == '\'' ) /* force device... */ option++; pcm_name = option; n = strlen( pcm_name ); } option += n + ( tmp == ',' ); } /* Open the sound device */ if( pcm_name == NULL || *pcm_name == '\0' ) pcm_name = "default"; if( snd_pcm_open( &pcm_handle, pcm_name , stream, 0 ) < 0 ) { if( strcmp( pcm_name, "default" ) == 0 ) { /* we try a last one: plughw:0,0 but what a weired ALSA conf.... */ if( snd_pcm_open( &pcm_handle, "plughw:0,0", stream, 0 ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't open sound device 'default' and 'plughw:0,0' check ALSA configuration." ); init_running = 0; return 1; } else { if( first_init ) fprintf( stderr, "Couldn't open sound device 'default', using 'plughw:0,0' check ALSA configuration.\n" ); } } settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't open sound device '%s'.", pcm_name ); init_running = 0; return 1; } /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca( &hw_params ); /* Init hw_params with full configuration space */ if( snd_pcm_hw_params_any( pcm_handle, hw_params ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't get configuration space on sound device '%s'.", pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( snd_pcm_hw_params_set_access( pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ) < 0) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't set access interleaved on '%s'.", pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } /* Set sample format */ if( snd_pcm_hw_params_set_format( pcm_handle, hw_params, #if defined WORDS_BIGENDIAN SND_PCM_FORMAT_S16_BE #else SND_PCM_FORMAT_S16_LE #endif ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't set format on '%s'.", pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } ch = *stereoptr ? 2 : 1; if( snd_pcm_hw_params_set_channels( pcm_handle, hw_params, ch ) < 0 ) { fprintf( stderr, "Couldn't set %s to '%s'.\n", pcm_name, (*stereoptr ? "stereo" : "mono") ); ch = *stereoptr ? 1 : 2; /* try with opposite */ if( snd_pcm_hw_params_set_channels( pcm_handle, hw_params, ch ) < 0 ) { ui_error( UI_ERROR_ERROR, "couldn't set %s to '%s'.", pcm_name, (*stereoptr ? "stereo" : "mono") ); settings_current.sound = 0; snd_pcm_close( pcm_handle ); init_running = 0; return 1; } *stereoptr = *stereoptr ? 0 : 1; /* write back */ } framesize = ch << 1; /* we always use 16 bit sorry :-( */ /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ exact_rate = *freqptr; if( snd_pcm_hw_params_set_rate_near( pcm_handle, hw_params, &exact_rate, NULL ) < 0) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't set rate %d on '%s'.", *freqptr, pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( first_init && *freqptr != exact_rate ) { fprintf( stderr, "The rate %d Hz is not supported by your hardware. " "Using %d Hz instead.\n", *freqptr, exact_rate ); *freqptr = exact_rate; } if( bsize != 0 ) { exact_periodsize = sound_periodsize = bsize / nperiods; if( bsize < 1 ) { fprintf( stderr, "bad value for ALSA buffer size %i, using default.\n", val ); bsize = 0; } } if( bsize == 0 ) { hz = (float)machine_current->timings.processor_speed / machine_current->timings.tstates_per_frame; exact_periodsize = sound_periodsize = *freqptr / hz; } dir = -1; if( snd_pcm_hw_params_set_period_size_near( pcm_handle, hw_params, &exact_periodsize, &dir ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't set period size %d on '%s'.", (int)sound_periodsize, pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( first_init && ( exact_periodsize < sound_periodsize / 1.5 || exact_periodsize > sound_periodsize * 1.5 ) ) { fprintf( stderr, "The period size %d is not supported by your hardware. " "Using %d instead.\n", (int)sound_periodsize, (int)exact_periodsize ); } periods = nperiods; /* Set number of periods. Periods used to be called fragments. */ if( snd_pcm_hw_params_set_periods_near( pcm_handle, hw_params, &periods, NULL ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR, "couldn't set periods on '%s'.", pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( first_init && periods != nperiods ) { fprintf( stderr, "%d periods is not supported by your hardware. " "Using %d instead.\n", nperiods, periods ); } snd_pcm_hw_params_get_buffer_size( hw_params, &exact_bsize ); /* Apply HW parameter settings to */ /* PCM device and prepare device */ if( snd_pcm_hw_params( pcm_handle, hw_params ) < 0 ) { settings_current.sound = 0; ui_error( UI_ERROR_ERROR,"couldn't set hw_params on %s", pcm_name ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } snd_pcm_sw_params_alloca( &sw_params ); if( ( err = snd_pcm_sw_params_current( pcm_handle, sw_params ) ) < 0 ) { ui_error( UI_ERROR_ERROR,"couldn't get sw_params from %s: %s", pcm_name, snd_strerror ( err ) ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( ( err = snd_pcm_sw_params_set_start_threshold( pcm_handle, sw_params, exact_periodsize * ( nperiods - 1 ) ) ) < 0 ) { ui_error( UI_ERROR_ERROR,"couldn't set start_treshold on %s: %s", pcm_name, snd_strerror ( err ) ); snd_pcm_close( pcm_handle ); init_running = 0; return 1; } if( !avail_min ) avail_min = exact_periodsize >> 1; if( snd_pcm_sw_params_set_avail_min( pcm_handle, sw_params, avail_min ) < 0 ) { #if SND_LIB_VERSION < 0x10010 if( ( err = snd_pcm_sw_params_set_sleep_min( pcm_handle, sw_params, 1 ) ) < 0 ) { fprintf( stderr, "Unable to set minimal sleep 1 for %s: %s\n", pcm_name, snd_strerror ( err ) ); } #else fprintf( stderr, "Unable to set avail min %s: %s\n", pcm_name, snd_strerror( err ) ); #endif } #if SND_LIB_VERSION < 0x10010 if( ( err = snd_pcm_sw_params_set_xfer_align( pcm_handle, sw_params, 1 ) ) < 0 ) { ui_error( UI_ERROR_ERROR,"couldn't set xfer_allign on %s: %s", pcm_name, snd_strerror ( err ) ); init_running = 0; return 1; } #endif if( ( err = snd_pcm_sw_params( pcm_handle, sw_params ) ) < 0 ) { ui_error( UI_ERROR_ERROR,"couldn't set sw_params on %s: %s", pcm_name, snd_strerror ( err ) ); init_running = 0; return 1; } if( first_init ) snd_output_stdio_attach(&output, stdout, 0); first_init = 0; init_running = 0; return 0; /* success */ }
bool QAudioInputPrivate::open( QObject *input ) { // Open the Alsa capture device. bool rc = true; int err; unsigned int freakuency = frequency; if ((err = snd_pcm_open(&handle, m_device.constData(), //"plughw:0,0" SND_PCM_STREAM_CAPTURE, 0/*SND_PCM_ASYNC*/)) < 0) { qWarning( "QAudioInput: snd_pcm_open: error %d", err); rc = false; } else { snd_pcm_hw_params_t *hwparams; // We want non-blocking mode. snd_pcm_nonblock(handle, 1); // Set the desired parameters. snd_pcm_hw_params_alloca(&hwparams); err = snd_pcm_hw_params_any(handle, hwparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_any: err %d", err); } err = snd_pcm_hw_params_set_access(handle, hwparams, access); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_access: err %d",err); } err = snd_pcm_hw_params_set_format(handle, hwparams,format); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_format: err %d",err); } err = snd_pcm_hw_params_set_channels(handle,hwparams,(unsigned int)channels); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_channels: err %d",err); } err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err); } if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) { qWarning("QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency); } if ( samplesPerBlock != -1 ) { // Set buffer and period sizes based on the supplied block size. sample_size = (snd_pcm_uframes_t)( samplesPerBlock * channels / 8 ); err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err); } if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) { qWarning( "QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency); } err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } period_time = 1000000 * 256 / frequency; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err); } } else { // Use the largest buffer and period sizes we can. err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } period_time = 1000000 * 256 / frequency; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err); } } err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params: err %d",err); } int dir; unsigned int vval, vval2; snd_pcm_access_t aval; snd_pcm_format_t fval; snd_pcm_subformat_t sval; qLog(QAudioInput) << "PCM handle name = " << snd_pcm_name(handle); qLog(QAudioInput) << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle)); snd_pcm_hw_params_get_access(hwparams,&aval); vval = (unsigned int)aval; if ( (int)vval != (int)access ) { qLog(QAudioInput) << QString("access type not set, want %1 got %2") .arg(snd_pcm_access_name((snd_pcm_access_t)access)) .arg(snd_pcm_access_name((snd_pcm_access_t)vval)); access = (snd_pcm_access_t)vval; } qLog(QAudioInput) << "access type = " << snd_pcm_access_name((snd_pcm_access_t)vval); snd_pcm_hw_params_get_format(hwparams, &fval); vval = (unsigned int)fval; if ( (int)vval != (int)format ) { qLog(QAudioInput) << QString("format type not set, want %1 got %2") .arg(snd_pcm_format_name((snd_pcm_format_t)format)) .arg(snd_pcm_format_name((snd_pcm_format_t)vval)); format = (snd_pcm_format_t)vval; } qLog(QAudioInput) << QString("format = '%1' (%2)") .arg(snd_pcm_format_name((snd_pcm_format_t)vval)) .arg(snd_pcm_format_description((snd_pcm_format_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_subformat(hwparams,&sval); vval = (unsigned int)sval; qLog(QAudioInput) << QString("subformat = '%1' (%2)") .arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval)) .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_channels(hwparams, &vval); if ( (int)vval != (int)channels ) { qLog(QAudioInput) << QString("channels type not set, want %1 got %2").arg(channels).arg(vval); channels = vval; } qLog(QAudioInput) << "channels = " << vval; snd_pcm_hw_params_get_rate(hwparams, &vval, &dir); if ( (int)vval != (int)frequency ) { qLog(QAudioInput) << QString("frequency type not set, want %1 got %2").arg(frequency).arg(vval); frequency = vval; } qLog(QAudioInput) << "rate =" << vval << " bps"; snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); qLog(QAudioInput) << "period time =" << period_time << " us"; snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir); qLog(QAudioInput) << "period size =" << (int)period_size; snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); qLog(QAudioInput) << "buffer time =" << buffer_time; snd_pcm_hw_params_get_buffer_size(hwparams,(snd_pcm_uframes_t *) &buffer_size); qLog(QAudioInput) << "buffer size =" << (int)buffer_size; snd_pcm_hw_params_get_periods(hwparams, &vval, &dir); qLog(QAudioInput) << "periods per buffer =" << vval; snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2); qLog(QAudioInput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData(); vval = snd_pcm_hw_params_get_sbits(hwparams); qLog(QAudioInput) << "significant bits =" << vval; snd_pcm_hw_params_get_tick_time(hwparams,&vval, &dir); qLog(QAudioInput) << "tick time =" << vval; vval = snd_pcm_hw_params_is_batch(hwparams); qLog(QAudioInput) << "is batch =" << vval; vval = snd_pcm_hw_params_is_block_transfer(hwparams); qLog(QAudioInput) << "is block transfer =" << vval; vval = snd_pcm_hw_params_is_double(hwparams); qLog(QAudioInput) << "is double =" << vval; vval = snd_pcm_hw_params_is_half_duplex(hwparams); qLog(QAudioInput) << "is half duplex =" << vval; vval = snd_pcm_hw_params_is_joint_duplex(hwparams); qLog(QAudioInput) << "is joint duplex =" << vval; vval = snd_pcm_hw_params_can_overrange(hwparams); qLog(QAudioInput) << "can overrange =" << vval; vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams); qLog(QAudioInput) << "can mmap =" << vval; vval = snd_pcm_hw_params_can_pause(hwparams); qLog(QAudioInput) << "can pause =" << vval; vval = snd_pcm_hw_params_can_resume(hwparams); qLog(QAudioInput) << "can resume =" << vval; vval = snd_pcm_hw_params_can_sync_start(hwparams); qLog(QAudioInput) << "can sync start =" << vval; snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_sw_params_current(handle, swparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_current: err %d",err); } err = snd_pcm_sw_params_set_start_threshold(handle,swparams,period_size); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_start_threshold: err %d",err); } err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_avail_min: err %d",err); } err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_xfer_align: err %d",err); } err = snd_pcm_sw_params(handle, swparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params: err %d",err); } snd_pcm_prepare(handle); snd_pcm_start(handle); int count = snd_pcm_poll_descriptors_count(handle); pollfd *pfds = new pollfd[count]; snd_pcm_poll_descriptors(handle, pfds, count); for (int i = 0; i < count; ++i) { if ((pfds[i].events & POLLIN) != 0) { notifier = new QSocketNotifier(pfds[i].fd, QSocketNotifier::Read); QObject::connect(notifier, SIGNAL(activated(int)), input, SIGNAL(readyRead())); break; } } if (notifier == NULL) { rc = false; } delete pfds; } return rc; }
main (int argc, char *argv[]) { int i; int err; short buf[128]; snd_pcm_t *capture_handle; snd_pcm_hw_params_t *hw_params; if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1], snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, 44100, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare (capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } for (i = 0; i < 10; ++i) { if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) { fprintf (stderr, "read from audio interface failed (%s)\n", snd_strerror (err)); exit (1); } } snd_pcm_close (capture_handle); exit (0); }
void* play_thread(void *argv) { char *__file_name = argv; struct WAVE *_wave; #ifdef SOLO _wave = (struct WAVE*)malloc(sizeof(struct WAVE)); memset(&_wave, 0, sizeof(struct _wave)); if(!wave_read_file(argv, &_wave )){ goto ERR; } #else if(!list_count){ fprintf(stderr,"[PLAY]: Not such wav sound file.\nPlease call \'play_read_filelist(DIR_PATH)\'\n"); exit(1); } for(_wave=head;;_wave=_wave->next){ if(!strcmp(_wave->file_name, __file_name))break; if(head->prev == _wave){ fprintf(stderr,"[PLAY]: Invalid file_name...\n"); return NULL; } } #endif if(DISP) fprintf(stderr,"[PLAY]: Player will be playing \"%s\".\n",__file_name); snd_pcm_t *handle; // handle for sound_device snd_pcm_hw_params_t *params; // params for sound_device int result_func = 0; // result for function return unsigned int sampling_rate = _wave->rate; // sampling rate int dir; // sub unit direction snd_pcm_uframes_t frames = 32; // size of frame unsigned int buffer_size; // buffer_size for frame int16_t *frameBuffer=NULL; // buffer for frame unsigned int approximate_period; // period[us] {// open the pcm device // open pcm device result_func = snd_pcm_open( &handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if ( result_func < 0 ) { fprintf(stderr, "[PLAY]: unable to open pcm device :%s\n", snd_strerror(result_func)); goto ERR; } } {// set parameter to device // allocate device params snd_pcm_hw_params_alloca(¶ms); // get default param snd_pcm_hw_params_any(handle, params); // set parameter Interleaved mode snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); // set format parameter : monoral 1ch 16bit LittleEndian snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); // set output_device parameter stereo 2ch snd_pcm_hw_params_set_channels(handle, params, _wave->channel); // approximates to a specified sampling rate // pcm PCM handle // params Configuration space // val approximate target rate / returned approximate set rate // dir Sub unit direction snd_pcm_hw_params_set_rate_near( handle, params, &sampling_rate, &dir); // set parameter size of frame snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); // set parameter to hardware_device result_func = snd_pcm_hw_params(handle, params); // err check if (result_func < 0) { fprintf(stderr, "[PLAY]: unable to set hw parameters: %s\n", snd_strerror(result_func)); goto ERR; } // get bufferSize / frame snd_pcm_hw_params_get_period_size(params, &frames, &dir); // calculate buffer_size buffer_size = frames * 2; /*????????? 48000,monoral ver */ // allocate buffer frameBuffer = (int16_t *)malloc(buffer_size); memset(frameBuffer, 0, sizeof(*frameBuffer)); // get playback period // params Configuration space // val Returned approximate period duration in us // dir Sub unit direction snd_pcm_hw_params_get_period_time(params, &approximate_period, &dir); } { // playback process // playback time unsigned int ptime = approximate_period * 2 * 10; // playback while ( ptime-- ) { result_func = fread( frameBuffer, sizeof(unsigned char), buffer_size, _wave->fp); // data is ended if ( result_func == 0 ) { //fprintf(stdout, "[PLAY]: end of input devce\n"); break; } // buffer_size is not correct if ( result_func != buffer_size ) { /* fprintf(stderr, "short read: read %d bytes\n", result_func); */ break; } // playback result_func = snd_pcm_writei( handle, frameBuffer, frames); } } // for unplayed frame,wait sound finish snd_pcm_drain(handle); if(DISP) fprintf(stderr,"[PLAY]: Finished playing %s.\n",__file_name); ERR : { // release if ( frameBuffer != NULL ){ free(frameBuffer); } if ( handle != NULL ) { snd_pcm_close(handle); } } return NULL; }
bool AlsaSource::SetupHW () { bool result = false; bool rw_available = false; bool mmap_available = false; #if DEBUG bool debug = debug_flags & RUNTIME_DEBUG_AUDIO; #else bool debug = false; #endif snd_pcm_hw_params_t *params = NULL; snd_output_t *output = NULL; guint32 buffer_time = 100000; // request 0.1 seconds of buffer time. int err = 0; int dir = 0; unsigned int rate = GetSampleRate (); unsigned int actual_rate = rate; guint32 channels = GetChannels (); if (debug) { err = snd_output_stdio_attach (&output, stdout, 0); if (err < 0) LOG_AUDIO ("AlsaSource::SetupHW (): Could not create alsa output: %s\n", snd_strerror (err)); } err = snd_pcm_hw_params_malloc (¶ms); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (malloc): %s\n", snd_strerror (err)); return false; } // choose all parameters err = snd_pcm_hw_params_any (pcm, params); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (no configurations available): %s\n", snd_strerror (err)); goto cleanup; } if (debug && output != NULL) { LOG_AUDIO ("AlsaSource::SetupHW (): hw configurations:\n"); snd_pcm_hw_params_dump (params, output); } // enable software resampling err = snd_pcm_hw_params_set_rate_resample (pcm, params, 1); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (could not enable resampling): %s\n", snd_strerror (err)); goto cleanup; } // test for available transfer modes if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_MMAP)) { err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: RW access mode not supported (%s).\n", snd_strerror (err)); } else { rw_available = true; } } if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_RW)) { err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: MMAP access mode not supported (%s).\n", snd_strerror (err)); } else { mmap_available = true; } } if (mmap_available) { mmap = true; } else if (rw_available) { mmap = false; } else { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed, no available access mode\n"); goto cleanup; } LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: using %s access mode.\n", mmap ? "MMAP" : "RW"); // set transfer mode (mmap or rw in our case) err = snd_pcm_hw_params_set_access (pcm, params, mmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (access type not available for playback): %s\n", snd_strerror (err)); goto cleanup; } // set audio format switch (GetInputBytesPerSample ()) { case 1: // 8 bit audio err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16); SetOutputBytesPerSample (2); break; case 2: // 16 bit audio err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16); SetOutputBytesPerSample (2); break; case 3: // 24 bit audio // write as 32 bit audio, this is a lot easier to write to than 24 bit. err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S32); SetOutputBytesPerSample (4); break; default: LOG_AUDIO ("AlsaSource::SetupHW (): Invalid input bytes per sample, expected 1, 2 or 3, got %i\n", GetInputBytesPerSample ()); goto cleanup; } if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample format not available for playback): %s\n", snd_strerror (err)); goto cleanup; } // set channel count err = snd_pcm_hw_params_set_channels (pcm, params, channels); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (channels count %i not available for playback): %s\n", channels, snd_strerror (err)); goto cleanup; } // set sample rate err = snd_pcm_hw_params_set_rate_near (pcm, params, &actual_rate, 0); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback): %s\n", rate, snd_strerror (err)); goto cleanup; } else if (actual_rate != rate) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback, only got %i Hz).\n", rate, actual_rate); goto cleanup; } // set the buffer time err = snd_pcm_hw_params_set_buffer_time_near (pcm, params, &buffer_time, &dir); if (err < 0) { LOG_AUDIO ("AudioNode::SetupHW (): Audio HW setup failed (unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror (err)); goto cleanup; } // write the parameters to device err = snd_pcm_hw_params (pcm, params); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (unable to set hw params for playback: %s)\n", snd_strerror (err)); if (debug && output != NULL) { LOG_AUDIO ("AlsaSource::SetupHW (): current hw configurations:\n"); snd_pcm_hw_params_dump (params, output); } goto cleanup; } if (debug) { LOG_AUDIO ("AlsaSource::SetupHW (): hardware pause support: %s\n", snd_pcm_hw_params_can_pause (params) == 0 ? "no" : "yes"); LOG_AUDIO ("AlsaSource::SetupHW (): succeeded\n"); if (output != NULL) snd_pcm_hw_params_dump (params, output); } result = true; cleanup: snd_pcm_hw_params_free (params); return result; }
void SetupSound(void) { snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; snd_pcm_status_t *status; int pspeed; int pchannels; int format; int buffer_time; int period_time; int err; if(iDisStereo) pchannels=1; else pchannels=2; pspeed=48000; format=SND_PCM_FORMAT_S16_LE; buffer_time=500000; period_time=buffer_time/4; if((err=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0) { printf("Audio open error: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_nonblock(handle, 0))<0) { printf("Can't set blocking moded: %s\n", snd_strerror(err)); return; } snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); if((err=snd_pcm_hw_params_any(handle, hwparams))<0) { printf("Broken configuration for this PCM: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0) { printf("Access type not available: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0) { printf("Sample format not available: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0) { printf("Channels count not available: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0) { printf("Rate not available: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0) { printf("Buffer time error: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0) { printf("Period time error: %s\n", snd_strerror(err)); return; } if((err=snd_pcm_hw_params(handle, hwparams))<0) { printf("Unable to install hw params: %s\n", snd_strerror(err)); return; } snd_pcm_status_alloca(&status); if((err=snd_pcm_status(handle, status))<0) { printf("Unable to get status: %s\n", snd_strerror(err)); return; } buffer_size=snd_pcm_status_get_avail(status); }
/* Initialise audio devices. */ int digi_init() { int err, tmp; char *device = "plughw:0,0"; snd_pcm_hw_params_t *params; pthread_attr_t attr; pthread_mutexattr_t mutexattr; //added on 980905 by adb to init sound kill system memset(SampleHandles, 255, sizeof(SampleHandles)); //end edit by adb /* Open the ALSA sound device */ if ((err = snd_pcm_open(&snd_devhandle, device, SND_PCM_STREAM_PLAYBACK)) < 0) { con_printf(CON_CRITICAL, "open failed: %s\n", snd_strerror( err )); return -1; } snd_pcm_hw_params_alloca(¶ms); err = snd_pcm_hw_params_any(snd_devhandle, params); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(snd_devhandle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(snd_devhandle, params, SND_PCM_FORMAT_U8); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels(snd_devhandle, params, 2); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } tmp = 11025; err = snd_pcm_hw_params_set_rate_near(snd_devhandle, params, &tmp, NULL); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } snd_pcm_hw_params_set_periods(snd_devhandle, params, 3, 0); snd_pcm_hw_params_set_buffer_size(snd_devhandle,params, (SOUND_BUFFER_SIZE*3)/2); err = snd_pcm_hw_params(snd_devhandle, params); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } /* Start the mixer thread */ /* We really should check the results of these */ pthread_mutexattr_init(&mutexattr); pthread_mutex_init(&mutex,&mutexattr); pthread_mutexattr_destroy(&mutexattr); if (pthread_attr_init(&attr) != 0) { con_printf(CON_CRITICAL, "failed to init attr\n"); snd_pcm_close( snd_devhandle ); return -1; } pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&thread_id,&attr,mixer_thread,NULL); pthread_attr_destroy(&attr); digi_initialised = 1; return 0; }
/** * This method prepares ALSA system for 22050hz signed 16bits Little Endian * playback. */ void SoundThread::initAlsa() { int err; ostringstream oss; /* Get a handle on the PCM device. */ if ((err = snd_pcm_open (&playback_handle, deviceName, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { oss << "cannot open audio device : " << deviceName << snd_strerror(err) << endl; throw oss.str(); } /* Allocate snd_pcm_hw_params_t structure. */ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { oss << "cannot allocate hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Retrieve current parameters. */ if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { oss << "cannot initialize hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample are NON Interleaved (mono !) */ if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) { oss << "cannot set access type : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample format: Signed 16bit little endian. */ if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { oss << "cannot set sample format : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the Sample rate. */ if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, 22050, 0)) < 0) { oss << "cannot set sample rate : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Channel number (MONO). */ if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0) { oss << "cannot set channel count : " << snd_strerror (err) << endl; throw oss.str(); } if ((err = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, 2048)) < 0) { oss << "cannot set channel buffer size : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply these parameters. */ if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { oss << "cannot apply parameters : " << snd_strerror (err) << endl; throw oss.str(); } snd_pcm_uframes_t bufferSize; snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize ); //cout << "initAlsa: Buffer size = " << bufferSize << " frames." << endl; /* Free memoray allocated for snd_pcm_hw_params_t */ snd_pcm_hw_params_free (hw_params); /* tell ALSA to wake us up whenever 4096 or more frames of playback data can be delivered. Also, tell ALSA that we'll start the device ourselves. */ /* Allocate snd_pcm_sw_params_t structure. */ if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { oss << "cannot allocate software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Get the current software configuration*/ if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) { oss << "cannot initialize software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the wake up point to 2048 (92.9 ms). The minimum data available before asking*/ /* for new ones. */ if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 2048U)) < 0) { oss << "cannot set minimum available count : " << snd_strerror (err) << endl; throw oss.str(); } /* Set when ALSA starts to play. */ if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 1024U)) < 0) { oss << "cannot set start mode : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply parameters. */ if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) { oss << "cannot apply software parameters : " << snd_strerror (err) << endl; throw oss.str(); } /* the interface will interrupt the kernel every 4096 frames, and ALSA will wake up this program very soon after that. */ if ((err = snd_pcm_prepare (playback_handle)) < 0) { oss << "cannot prepare audio interface for use : " << snd_strerror (err) << endl; throw oss.str(); } }
Player::Player() { // printf("Player::Player()\n"); int rc=0; unsigned int val=0; int dir=0; /* Open PCM device for playback. */ rc = snd_pcm_open(&(this->m_pHandle), "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { printf("unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&(this->m_pParams)); /* Fill it in with default values. */ rc = snd_pcm_hw_params_any(this->m_pHandle, this->m_pParams); if (rc < 0) { printf("Can not configure this PCM device: %s\n", snd_strerror(rc)); exit(1); } /* Set the desired hardware parameters. */ /* Interleaved mode */ rc = snd_pcm_hw_params_set_access(this->m_pHandle, this->m_pParams, SND_PCM_ACCESS_RW_INTERLEAVED); if (rc < 0) { printf("Failed to set PCM device to interleaved: %s\n", snd_strerror(rc)); exit(1); } /* Signed 16-bit little-endian format */ rc = snd_pcm_hw_params_set_format(this->m_pHandle, this->m_pParams, SND_PCM_FORMAT_S16_LE); if (rc < 0) { printf("Failed to set PCM device to 16-bit signed PCM: %s\n", snd_strerror(rc)); exit(1); } /* Two channels (mono) */ rc = snd_pcm_hw_params_set_channels(this->m_pHandle, this->m_pParams,channels); if (rc < 0) { printf("Failed to set PCM device to mono: %s\n", snd_strerror(rc)); exit(1); } /* 44100 bits/second sampling rate (CD quality) */ val = rate; rc = snd_pcm_hw_params_set_rate_near(this->m_pHandle, this->m_pParams, &val, 0); if (rc < 0) { printf("Failed to set PCM device to sample rate =%d: %s\n", rate,snd_strerror(rc)); exit(1); } if(val != rate){ printf("Rate doesn't match (request %iHz, get %iHz\n",rate,val); exit(1); } rc = snd_pcm_hw_params_set_buffer_time_near(this->m_pHandle, this->m_pParams, &buffer_time, &dir); if (rc < 0) { fprintf(stderr, "Failed to set PCM device to buffer time=%d: %s\n", val,snd_strerror(rc)); exit(1); } rc = snd_pcm_hw_params_set_period_time_near(this->m_pHandle, this->m_pParams, &period_time, &dir); if (rc < 0) { fprintf(stderr, "Failed to set PCM device to period time=%d: %s\n", val,snd_strerror(rc)); exit(1); } //chunk size rc = snd_pcm_hw_params_get_period_size(this->m_pParams, &period_size, &dir); if(rc < 0){ fprintf(stderr, "Failed to get period size for capture: %s\n", snd_strerror(rc)); exit(1); } this->m_frames = period_size; rc = snd_pcm_hw_params_get_buffer_size(this->m_pParams, &buffer_size); if(rc < 0){ fprintf(stderr, "Failed to get buffer size for capture: %s\n", snd_strerror(rc)); exit(1); } #ifdef DEBUG printf("Recorder alsa driver hw params setting\n"); printf("period size =%d frames\n", (int)period_size); printf("buffer size =%d frames\n", (int)buffer_size); snd_pcm_hw_params_get_period_time(this->m_pParams,&val, &dir); printf("period time =%d us\n",val); snd_pcm_hw_params_get_buffer_time(this->m_pParams,&val, &dir); printf("buffer time =%d us\n", val); snd_pcm_hw_params_get_periods(this->m_pParams, &val, &dir); printf("period per buffer =%d frames\n", val); #endif /* Write the parameters to the driver */ rc = snd_pcm_hw_params(this->m_pHandle, this->m_pParams); if (rc < 0) { printf("unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } #ifdef ALSA_OPT snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); /* get the current swparams */ rc = snd_pcm_sw_params_current(this->m_pHandle, swparams); if (rc < 0) { printf("Unable to determine current swparams for playback: %s\n", snd_strerror(rc)); exit(1); } /* start the transfer when the buffer is almost full: */ /* (buffer_size / avail_min) * avail_min */ rc = snd_pcm_sw_params_set_start_threshold(this->m_pHandle, swparams, (buffer_size / period_size) * period_size); if (rc < 0) { printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(rc)); exit(1); } rc = snd_pcm_sw_params_set_avail_min(this->m_pHandle, swparams, period_size); if (rc < 0) { printf("Unable to set avail min for playback: %s\n", snd_strerror(rc)); exit(1); } /* write the parameters to the playback device */ rc = snd_pcm_sw_params(this->m_pHandle, swparams); if (rc < 0) { printf("Unable to set sw params for playback: %s\n", snd_strerror(rc)); exit(1); } #endif }
/*------------------------------------------------------------------------------ * Open the audio source *----------------------------------------------------------------------------*/ bool AlsaDspSource :: open ( void ) throw ( Exception ) { unsigned int u; snd_pcm_format_t format; snd_pcm_hw_params_t *hwParams; if ( isOpen() ) { return false; } switch ( getBitsPerSample() ) { case 8: format = SND_PCM_FORMAT_S8; break; case 16: format = SND_PCM_FORMAT_S16; break; default: return false; } if (snd_pcm_open(&captureHandle, pcmName, SND_PCM_STREAM_CAPTURE, 0) < 0) { captureHandle = 0; return false; } if (snd_pcm_hw_params_malloc(&hwParams) < 0) { close(); throw Exception( __FILE__, __LINE__, "can't alloc hardware "\ "parameter structure"); } if (snd_pcm_hw_params_any(captureHandle, hwParams) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't initialize hardware "\ "parameter structure"); } if (snd_pcm_hw_params_set_access(captureHandle, hwParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set access type"); } if (snd_pcm_hw_params_set_format(captureHandle, hwParams, format) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set sample format"); } u = getSampleRate(); if (snd_pcm_hw_params_set_rate_near(captureHandle, hwParams, &u, 0) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set sample rate", u); } u = getChannel(); if (snd_pcm_hw_params_set_channels(captureHandle, hwParams, u) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set channels", u); } u = 4; if (snd_pcm_hw_params_set_periods_near(captureHandle, hwParams, &u, 0) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set interrupt frequency"); } u = getBufferTime(); if (snd_pcm_hw_params_set_buffer_time_near(captureHandle, hwParams, &u, 0) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set buffer size"); } if (snd_pcm_hw_params(captureHandle, hwParams) < 0) { snd_pcm_hw_params_free(hwParams); close(); throw Exception( __FILE__, __LINE__, "can't set hardware parameters"); } snd_pcm_hw_params_free(hwParams); if (snd_pcm_prepare(captureHandle) < 0) { close(); throw Exception( __FILE__, __LINE__, "can't prepare audio interface "\ "for use"); } bytesPerFrame = getChannel() * getBitsPerSample() / 8; return true; }
static void SetOptions(unsigned int rate, int opt) { int err; snd_pcm_format_t format; unsigned int val; /* start with setting default values, if we bail out */ plrRate=rate; plrOpt=opt; alsaOpenDevice(); if (!alsa_pcm) return; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_hw_params_any(alsa_pcm, hwparams) = "); #endif if ((err=snd_pcm_hw_params_any(alsa_pcm, hwparams))<0) /* we need to check for <0 here, due to a bug in the ALSA PulseAudio plugin */ { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_any() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_pcm_hw_params_set_access(alsa_pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) = "); #endif if ((err=snd_pcm_hw_params_set_access(alsa_pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_set_access() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); #endif if (opt&PLR_16BIT) if (opt&PLR_SIGNEDOUT) format=SND_PCM_FORMAT_S16; else format=SND_PCM_FORMAT_U16; else if (opt&PLR_SIGNEDOUT) format=SND_PCM_FORMAT_S8; else format=SND_PCM_FORMAT_U8; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, format %i) = ", format); #endif if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, format))) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S16) = "); #endif if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S16))==0) { opt|=PLR_16BIT|PLR_SIGNEDOUT; } else { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U16) = "); #endif if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U16))==0) { opt&=~(PLR_16BIT|PLR_SIGNEDOUT); opt|=PLR_16BIT; } else { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S8) = "); #endif if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S8))>=0) { opt&=~(PLR_16BIT|PLR_SIGNEDOUT); opt|=PLR_SIGNEDOUT; } else { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U8) = "); #endif if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U8))>=0) { opt&=~(PLR_16BIT|PLR_SIGNEDOUT); } else { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_set_format() failed: %s\n", snd_strerror(-err)); return; } } } } } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); #endif bit16=!!(opt&PLR_16BIT); if (opt&PLR_STEREO) val=2; else val=1; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &channels=%i) = ", val); #endif if ((err=snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &val))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_set_channels_near() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok (channels=%i)\n", val); #endif if (val==1) { stereo=0; opt&=~PLR_STEREO; } else if (val==2) { stereo=1; opt|=PLR_STEREO; } else { fprintf(stderr, "ALSA: snd_pcm_hw_params_set_channels_near() gave us %d channels\n", val); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &rate = %i, 0) = ", rate); #endif if ((err=snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &rate, 0))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_set_rate_near() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok, rate=%i\n", rate); #endif if (rate==0) { fprintf(stderr, "ALSA: No usable samplerate available.\n"); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams, 500000 uS, 0) = "); #endif val = 500000; if ((err=snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams, &val, 0))) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params_set_buffer_time_near() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok, latency = %d uS\n", val); fprintf(stderr, "ALSA snd_pcm_hw_params(alsa_pcm, hwparams) = "); #endif if ((err=snd_pcm_hw_params(alsa_pcm, hwparams))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_hw_params() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_pcm_sw_params_current(alsa_pcm, swparams) = "); #endif if ((err=snd_pcm_sw_params_current(alsa_pcm, swparams))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_sw_params_any() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_pcm_sw_params(alsa_pcm, swparams) = "); #endif if ((err=snd_pcm_sw_params(alsa_pcm, swparams))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_pcm_sw_params() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); #endif plrRate=rate; plrOpt=opt; }
static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm) { snd_pcm_hw_params_t *params; unsigned int buffer_time = 0; unsigned int period_time = 0; unsigned int rate; int err; const char *device_name = snd_pcm_name(sndpcm->handle); /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ err = snd_pcm_hw_params_any(sndpcm->handle, params); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("default params: %s: %s(%d)\n"), device_name, snd_strerror(err), err); return err; } /* Set access mode */ err = snd_pcm_hw_params_set_access(sndpcm->handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("access type: %s: %s(%d)\n"), device_name, snd_strerror(err), err); return err; } /* Set format */ err = snd_pcm_hw_params_set_format(sndpcm->handle, params, bat->format); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("PCM format: %d %s: %s(%d)\n"), bat->format, device_name, snd_strerror(err), err); return err; } /* Set channels */ err = snd_pcm_hw_params_set_channels(sndpcm->handle, params, bat->channels); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("channel number: %d %s: %s(%d)\n"), bat->channels, device_name, snd_strerror(err), err); return err; } /* Set sampling rate */ rate = bat->rate; err = snd_pcm_hw_params_set_rate_near(sndpcm->handle, params, &bat->rate, 0); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("sample rate: %d %s: %s(%d)\n"), bat->rate, device_name, snd_strerror(err), err); return err; } if ((float) rate * (1 + RATE_RANGE) < bat->rate || (float) rate * (1 - RATE_RANGE) > bat->rate) { fprintf(bat->err, _("Invalid parameters: sample rate: ")); fprintf(bat->err, _("requested %dHz, got %dHz\n"), rate, bat->rate); return -EINVAL; } if (snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0) < 0) { fprintf(bat->err, _("Get parameter from device error: ")); fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"), buffer_time, device_name, snd_strerror(err), err); return -EINVAL; } if (buffer_time > MAX_BUFFERTIME) buffer_time = MAX_BUFFERTIME; period_time = buffer_time / DIV_BUFFERTIME; /* Set buffer time and period time */ err = snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, params, &buffer_time, 0); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"), buffer_time, device_name, snd_strerror(err), err); return err; } err = snd_pcm_hw_params_set_period_time_near(sndpcm->handle, params, &period_time, 0); if (err < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("period time: %d %s: %s(%d)\n"), period_time, device_name, snd_strerror(err), err); return err; } /* Write the parameters to the driver */ if (snd_pcm_hw_params(sndpcm->handle, params) < 0) { fprintf(bat->err, _("Set parameter to device error: ")); fprintf(bat->err, _("hw params: %s: %s(%d)\n"), device_name, snd_strerror(err), err); return -EINVAL; } err = snd_pcm_hw_params_get_period_size(params, &sndpcm->period_size, 0); if (err < 0) { fprintf(bat->err, _("Get parameter from device error: ")); fprintf(bat->err, _("period size: %lu %s: %s(%d)\n"), sndpcm->period_size, device_name, snd_strerror(err), err); return err; } err = snd_pcm_hw_params_get_buffer_size(params, &sndpcm->buffer_size); if (err < 0) { fprintf(bat->err, _("Get parameter from device error: ")); fprintf(bat->err, _("buffer size: %lu %s: %s(%d)\n"), sndpcm->buffer_size, device_name, snd_strerror(err), err); return err; } if (sndpcm->period_size == sndpcm->buffer_size) { fprintf(bat->err, _("Invalid parameters: can't use period ")); fprintf(bat->err, _("equal to buffer size (%lu)\n"), sndpcm->period_size); return -EINVAL; } err = snd_pcm_format_physical_width(bat->format); if (err < 0) { fprintf(bat->err, _("Invalid parameters: ")); fprintf(bat->err, _("snd_pcm_format_physical_width: %d\n"), err); return err; } sndpcm->sample_bits = err; sndpcm->frame_bits = sndpcm->sample_bits * bat->channels; /* Calculate the period bytes */ sndpcm->period_bytes = sndpcm->period_size * sndpcm->frame_bits / 8; sndpcm->buffer = (char *) malloc(sndpcm->period_bytes); if (sndpcm->buffer == NULL) { fprintf(bat->err, _("Not enough memory: size=%zd\n"), sndpcm->period_bytes); return -ENOMEM; } return 0; }
int setup_pcmdev(char *pcm_name) { snd_pcm_hw_params_t *params; snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; int rate = 44100, dir; snd_pcm_uframes_t persize, persize2; int maxrate, minrate; unsigned int pertime, perTmin, perTmax; snd_pcm_uframes_t bufsize, perSmin, perSmax, bufSmin, bufSmax; /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(¶ms); /* Open PCM device for playback. */ if (snd_pcm_open(&handle, pcm_name, stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", pcm_name); return(-1); } /* Init params with full configuration space */ if (snd_pcm_hw_params_any(handle, params) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); return(-1); } /* set interleaved mode */ if (snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } /* Set sample format */ if (snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE) < 0) { fprintf(stderr, "Error setting format.\n"); return(-1); } /* Set sample rate.*/ if (snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0) < 0) { fprintf(stderr, "Error setting rate.\n"); return(-1); } /* Set number of channels */ if (snd_pcm_hw_params_set_channels(handle, params, nchan) < 0) { fprintf(stderr, "Error setting channels.\n"); return(-1); } /* Set period size to n frames (samples). */ persize = 1024; dir=0; if (snd_pcm_hw_params_set_period_size_near(handle,params, &persize, &dir)< 0) { fprintf(stderr, "Error setting period size to %d.\n", (int) persize); return(-1); } /* Apply HW parameter settings to PCM device */ if (snd_pcm_hw_params(handle, params) < 0) { fprintf(stderr, "Error setting HW params.\n"); return(-1); } /*get some inof about the hardware*/ // printf("\n ---------- hardware parameters ------------ \n"); snd_pcm_hw_params_get_rate_min (params, &minrate, &dir); //printf("min rate: %d samples per sec\n",minrate); snd_pcm_hw_params_get_rate_max (params, &maxrate, &dir); //printf("max rate: %d samples per sec\n",maxrate); snd_pcm_hw_params_get_period_time (params, &pertime, &dir); //printf("period: %d microseconds\n",pertime); snd_pcm_hw_params_get_period_time_min (params, &perTmin, &dir); snd_pcm_hw_params_get_period_time_min (params, &perTmax, &dir); //printf("min period time: %d microseconds\n",perTmin); //printf("max period time: %d microseconds\n",perTmax); snd_pcm_hw_params_get_period_size (params, &persize2, &dir); //printf("period: %d frames\n",(int) persize2); snd_pcm_hw_params_get_period_size_min (params, &perSmin, &dir); snd_pcm_hw_params_get_period_size_min (params, &perSmax, &dir); //printf("min period size: %d frames\n",(int) perSmin); //printf("max period size: %d frames\n",(int) perSmax); snd_pcm_hw_params_get_buffer_size (params, &bufsize); //printf("buffer size: %d frames\n",(int) bufsize); snd_pcm_hw_params_get_buffer_size_min (params, &bufSmin); snd_pcm_hw_params_get_buffer_size_min (params, &bufSmax); //printf("min buffer size: %d frames\n",(int) bufSmin); //printf("max buffer size: %d frames\n",(int) bufSmax); return (double) persize2; }
static void alsa_configure (struct sound_device *sd) { int val, err, dir; unsigned uval; struct alsa_params *p = (struct alsa_params *) sd->data; snd_pcm_uframes_t buffer_size; eassert (p->handle != 0); err = snd_pcm_hw_params_malloc (&p->hwparams); if (err < 0) alsa_sound_perror ("Could not allocate hardware parameter structure", err); err = snd_pcm_sw_params_malloc (&p->swparams); if (err < 0) alsa_sound_perror ("Could not allocate software parameter structure", err); err = snd_pcm_hw_params_any (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not initialize hardware parameter structure", err); err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) alsa_sound_perror ("Could not set access type", err); val = sd->format; err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set sound format", err); uval = sd->sample_rate; err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0); if (err < 0) alsa_sound_perror ("Could not set sample rate", err); val = sd->channels; err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set channel count", err); err = snd_pcm_hw_params (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not set parameters", err); err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); if (err < 0) alsa_sound_perror ("Unable to get period size for playback", err); err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); if (err < 0) alsa_sound_perror ("Unable to get buffer size for playback", err); err = snd_pcm_sw_params_current (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to determine current swparams for playback", err); /* Start the transfer when the buffer is almost full */ err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, (buffer_size / p->period_size) * p->period_size); if (err < 0) alsa_sound_perror ("Unable to set start threshold mode for playback", err); /* Allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); if (err < 0) alsa_sound_perror ("Unable to set avail min for playback", err); err = snd_pcm_sw_params (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to set sw params for playback\n", err); snd_pcm_hw_params_free (p->hwparams); p->hwparams = NULL; snd_pcm_sw_params_free (p->swparams); p->swparams = NULL; err = snd_pcm_prepare (p->handle); if (err < 0) alsa_sound_perror ("Could not prepare audio interface for use", err); if (sd->volume > 0) { int chn; snd_mixer_t *handle; snd_mixer_elem_t *e; if (snd_mixer_open (&handle, 0) >= 0) { char const *file = string_default (sd->file, DEFAULT_ALSA_SOUND_DEVICE); if (snd_mixer_attach (handle, file) >= 0 && snd_mixer_load (handle) >= 0 && snd_mixer_selem_register (handle, NULL, NULL) >= 0) for (e = snd_mixer_first_elem (handle); e; e = snd_mixer_elem_next (e)) { if (snd_mixer_selem_has_playback_volume (e)) { long pmin, pmax, vol; snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); vol = pmin + (sd->volume * (pmax - pmin)) / 100; for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) snd_mixer_selem_set_playback_volume (e, chn, vol); } } snd_mixer_close (handle); } } }
static snd_pcm_uframes_t set_params(snd_pcm_t *handle, snd_pcm_stream_t stream) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t chunk_size = 0; snd_pcm_uframes_t start_threshold; unsigned period_time = 0; unsigned buffer_time = 0; size_t chunk_bytes = 0; int err; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for this PCM: no configurations available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Access type not available"); exit(EXIT_FAILURE); } printf("format = %s, channels = %d, rate = %d\n", snd_pcm_format_name(hwparams.format),hwparams.channels,hwparams.rate); //err = snd_pcm_hw_params_set_format(handle, params, hwparams.format); err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { printf("Sample format non available"); exit(EXIT_FAILURE); } //err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); err = snd_pcm_hw_params_set_channels(handle, params, 2); if (err < 0) { printf("Channels count non available"); exit(EXIT_FAILURE); } #if 0 //add by yjc 2012/08/21 err = set_audio_clk_freq(hwparams.rate); if (err < 0){ printf("set_audio_clk_freq fail..........\n"); exit(EXIT_FAILURE); } #endif err = snd_pcm_hw_params_set_rate(handle, params, hwparams.rate, 0); if (err < 0) { printf("Rate non available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); assert(err >= 0); if (buffer_time > 500000) buffer_time = 500000; period_time = buffer_time / 4; err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0); assert(err >= 0); err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); assert(err >= 0); err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to install hw params:"); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_period_size(params, &chunk_size, 0); snd_pcm_hw_params_get_buffer_size(params, &buffer_size); if (chunk_size == buffer_size) { printf("Can't use period equal to buffer size (%lu == %lu)", chunk_size, buffer_size); exit(EXIT_FAILURE); } snd_pcm_sw_params_current(handle, swparams); err = snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size); if(stream == SND_PCM_STREAM_PLAYBACK) start_threshold = (buffer_size / chunk_size) * chunk_size; else start_threshold = 1; err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); assert(err >= 0); err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, buffer_size); assert(err >= 0); if (snd_pcm_sw_params(handle, swparams) < 0) { printf("unable to install sw params:"); exit(EXIT_FAILURE); } //bits_per_sample = snd_pcm_format_physical_width(hwparams.format); bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); //bits_per_frame = bits_per_sample * hwparams.channels; bits_per_frame = bits_per_sample * 2; chunk_bytes = chunk_size * bits_per_frame / 8; printf("chunk_size = %d,chunk_bytes = %d,buffer_size = %d\n\n", (int)chunk_size,chunk_bytes,(int)buffer_size); return chunk_size; }
// input: ALSA void* input_alsa(void* data) { struct audio_data *audio = (struct audio_data *)data; signed char *buffer; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; snd_pcm_uframes_t frames; val = 44100; int i, n, o, size, dir, err; int tempr, templ; int radj, ladj; // alsa: open device to capture audio if ((err = snd_pcm_open(&handle, audio-> source, SND_PCM_STREAM_CAPTURE, 0) < 0)) { fprintf(stderr, "error opening stream: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } #ifdef DEBUG else printf("open stream successful\n"); #endif snd_pcm_hw_params_alloca(¶ms); //assembling params snd_pcm_hw_params_any (handle, params); //setting defaults or something snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //interleaved mode right left right left snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); //trying to set 16bit snd_pcm_hw_params_set_channels(handle, params, 2); //assuming stereo val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //trying 44100 rate frames = 256; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); //number of frames pr read err = snd_pcm_hw_params(handle, params); //attempting to set params if (err < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_format(params, (snd_pcm_format_t * )&val); //getting actual format //converting result to number of bits if (val < 6)audio->format = 16; else if (val > 5 && val < 10)audio->format = 24; else if (val > 9)audio->format = 32; snd_pcm_hw_params_get_rate(params, &audio->rate, &dir); //getting rate snd_pcm_hw_params_get_period_size(params, &frames, &dir); snd_pcm_hw_params_get_period_time(params, &val, &dir); size = frames * (audio->format / 8) * 2; // frames * bits/8 * 2 channels buffer = malloc(size); radj = audio->format / 4; //adjustments for interleaved ladj = audio->format / 8; o = 0; while (1) { err = snd_pcm_readi(handle, buffer, frames); if (err == -EPIPE) { /* EPIPE means overrun */ #ifdef DEBUG fprintf(stderr, "overrun occurred\n"); #endif snd_pcm_prepare(handle); } else if (err < 0) { #ifdef DEBUG fprintf(stderr, "error from read: %s\n", snd_strerror(err)); #endif } else if (err != (int)frames) { #ifdef DEBUG fprintf(stderr, "short read, read %d %d frames\n", err, (int)frames); #endif } //sorting out one channel and only biggest octet n = 0; //frame counter for (i = 0; i < size ; i = i + (ladj) * 2) { //first channel tempr = (buffer[i + (radj) - 1]); //other channel templ = (buffer[i + (ladj) - 1]); //first channel //using the 10 upper bits this would give me a vert res of 1024, enough... //tempr = ((buffer[i + (radj) - 1 ] << 2)); //lo = ((buffer[i + (radj) - 2] >> 6)); //if (lo < 0)lo = abs(lo) + 1; //if (tempr >= 0)tempr = tempr + lo; //if (tempr < 0)tempr = tempr - lo; //other channel //templ = (buffer[i + (ladj) - 1] << 2); //lo = (buffer[i + (ladj) - 2] >> 6); //if (lo < 0)lo = abs(lo) + 1; //if (templ >= 0)templ = templ + lo; //else templ = templ - lo; //mono: adding channels and storing it in the buffer if (audio->channels == 1) audio->audio_out_l[o] = (tempr + templ) / 2; //stereo storing channels in buffer if (audio->channels == 2) { audio->audio_out_l[o] = templ; audio->audio_out_r[o] = tempr; } //o++; //if (o == 2047) o = 0; o = (o + 1) % 2047; n++; } } }
static int setparams(int32 sps, snd_pcm_t * handle) { snd_pcm_hw_params_t *hwparams; unsigned int out_sps, buffer_time, period_time; int err; snd_pcm_hw_params_alloca(&hwparams); err = snd_pcm_hw_params_any(handle, hwparams); if (err < 0) { fprintf(stderr, "Can not configure this PCM device: %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { fprintf(stderr, "Failed to set PCM device to interleaved: %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16); if (err < 0) { fprintf(stderr, "Failed to set PCM device to 16-bit signed PCM: %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels(handle, hwparams, 1); if (err < 0) { fprintf(stderr, "Failed to set PCM device to mono: %s\n", snd_strerror(err)); return -1; } out_sps = sps; err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &out_sps, NULL); if (err < 0) { fprintf(stderr, "Failed to set sampling rate: %s\n", snd_strerror(err)); return -1; } if (abs(out_sps - sps) > SPS_EPSILON) { fprintf(stderr, "Available samping rate %d is too far from requested %d\n", out_sps, sps); return -1; } /* Set buffer time to the maximum. */ err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0); period_time = buffer_time / 4; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if (err < 0) { fprintf(stderr, "Failed to set period time to %u: %s\n", period_time, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if (err < 0) { fprintf(stderr, "Failed to set buffer time to %u: %s\n", buffer_time, snd_strerror(err)); return -1; } err = snd_pcm_hw_params(handle, hwparams); if (err < 0) { fprintf(stderr, "Failed to set hwparams: %s\n", snd_strerror(err)); return -1; } err = snd_pcm_nonblock(handle, 1); if (err < 0) { fprintf(stderr, "Failed to set non-blocking mode: %s\n", snd_strerror(err)); return -1; } return 0; }
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period) { int dir; int err; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_uframes_t period_size = period; snd_pcm_uframes_t buffer_size = PERIODS*period; static snd_output_t *jcd_out; AlsaDevice *dev = malloc(sizeof(*dev)); if (!dev) return NULL; dev->device_name = malloc(1+strlen(device_name)); if (!dev->device_name) { free(dev); return NULL; } strcpy(dev->device_name, device_name); dev->channels = channels; dev->period = period; err = snd_output_stdio_attach(&jcd_out, stdout, 0); if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev->device_name, snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_any (dev->capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_access (dev->capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_format (dev->capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_rate_near (dev->capture_handle, hw_params, &rate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); assert(0); } /*fprintf (stderr, "rate = %d\n", rate);*/ if ((err = snd_pcm_hw_params_set_channels (dev->capture_handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); assert(0); } period_size = period; dir = 0; if ((err = snd_pcm_hw_params_set_period_size_near (dev->capture_handle, hw_params, &period_size, &dir)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_periods (dev->capture_handle, hw_params, PERIODS, 0)) < 0) { fprintf (stderr, "cannot set number of periods (%s)\n", snd_strerror (err)); assert(0); } buffer_size = period_size * PERIODS; dir=0; if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->capture_handle, hw_params, &buffer_size)) < 0) { fprintf (stderr, "cannot set buffer time (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params (dev->capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set capture parameters (%s)\n", snd_strerror (err)); assert(0); } /*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/ snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_current (dev->capture_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_avail_min (dev->capture_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params (dev->capture_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_open (&dev->playback_handle, dev->device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev->device_name, snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_any (dev->playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_access (dev->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_format (dev->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_rate_near (dev->playback_handle, hw_params, &rate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); assert(0); } /*fprintf (stderr, "rate = %d\n", rate);*/ if ((err = snd_pcm_hw_params_set_channels (dev->playback_handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); assert(0); } period_size = period; dir = 0; if ((err = snd_pcm_hw_params_set_period_size_near (dev->playback_handle, hw_params, &period_size, &dir)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_periods (dev->playback_handle, hw_params, PERIODS, 0)) < 0) { fprintf (stderr, "cannot set number of periods (%s)\n", snd_strerror (err)); assert(0); } buffer_size = period_size * PERIODS; dir=0; if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->playback_handle, hw_params, &buffer_size)) < 0) { fprintf (stderr, "cannot set buffer time (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params (dev->playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot set playback parameters (%s)\n", snd_strerror (err)); assert(0); } /*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/ snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_current (dev->playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_avail_min (dev->playback_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_start_threshold (dev->playback_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set start mode (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params (dev->playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); assert(0); } snd_pcm_link(dev->capture_handle, dev->playback_handle); if ((err = snd_pcm_prepare (dev->capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_prepare (dev->playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); assert(0); } dev->readN = snd_pcm_poll_descriptors_count(dev->capture_handle); dev->writeN = snd_pcm_poll_descriptors_count(dev->playback_handle); dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd)); /*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/ if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN) { fprintf (stderr, "cannot obtain capture file descriptors (%s)\n", snd_strerror (err)); assert(0); } dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd)); if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN) { fprintf (stderr, "cannot obtain playback file descriptors (%s)\n", snd_strerror (err)); assert(0); } return dev; }
int AlsaAudioPlugin::init(shared_ptr<t_CPC> cpc, shared_ptr<t_PSG> psg) { if(!cpc->snd_enabled) { InfoLogMessage("[ALSA Audio Plugin] Not opening audio because disabled in the config"); return 0; } /* TODO */ unsigned int rate = cpc->snd_playback_rate; int channels = cpc->snd_stereo ? 2 : 1; snd_pcm_format_t format = SND_PCM_FORMAT_S16; switch(cpc->snd_bits) { case 8: format = SND_PCM_FORMAT_U8; break; case 16: format = SND_PCM_FORMAT_S16; break; case 24: format = SND_PCM_FORMAT_S24; break; case 32: format = SND_PCM_FORMAT_S32; break; default: WarningLogMessage("[ALSA Audio Plugin] Warning, %d bits format unknown, fallback to %s.", cpc->snd_bits, snd_pcm_format_name(format)); } int periods = 2; periodsize = 4096; unsigned int exact_rate; int dir, err; /* Handle for the PCM device */ //snd_pcm_t *pcm_handle; /* Playback stream */ snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; /* This structure contains information about */ /* the hardware and can be used to specify the */ /* configuration to be used for the PCM stream. */ snd_pcm_hw_params_t *hwparams; /* Name of the PCM device, like plughw:0,0 */ /* The first number is the number of the soundcard, */ /* the second number is the number of the device. */ char *pcm_name = strdup("plughw:0,0"); WarningLogMessage("TODO [%s:%d]: pcm_name need to be configurable.", __FILE__, __LINE__); /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); /* Open PCM. The last parameter of this function is the mode. */ /* If this is set to 0, the standard mode is used. Possible */ /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */ /* If SND_PCM_NONBLOCK is used, read / write access to the */ /* PCM device will return immediately. If SND_PCM_ASYNC is */ /* specified, SIGIO will be emitted whenever a period has */ /* been completely processed by the soundcard. */ if(err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error opening PCM device %s (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Init hwparams with full configuration space */ if(err = snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Can not configure PCM device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ /* There are also access types for MMAPed */ /* access, but this is beyond the scope */ /* of this introduction. */ if(err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting access on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set sample format */ if(err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting format %s on device %s. (Error: %s)", snd_pcm_format_name(format), pcm_name, snd_strerror(err)); return 1; } /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if 0 // Segfault... Humf... TODO exact_rate = rate; if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &dir) < 0) { ErrorLogMessage("Error setting rate (%d) on device %s.", rate, pcm_name); } if(dir != 0) { WarningLogMessage("The rate %d Hz is not supported by your hardware on device %s.\n" \ "==> Using %d Hz instead.", pcm_name, rate, exact_rate); } #else exact_rate = rate; if(err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, exact_rate, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting rate (%d) on device %s. (Error: %s)", rate, pcm_name, snd_strerror(err)); } #endif /* Set number of channels */ if(err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting channels (%d) on device %s. (Error: %s)", channels, pcm_name, snd_strerror(err)); return 1; } /* Set number of periods. Periods used to be called fragments. */ if(err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting periods (%d) on device %s. (Error: %s)", periods, pcm_name, snd_strerror(err)); return 1; } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ int buffer_size = (periodsize * periods) >> 2; if(err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, buffer_size) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting buffersize (%d) on device %s. (Error: %s)", buffer_size, pcm_name, snd_strerror(err)); return 1; } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if(err = snd_pcm_hw_params(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting HW params on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } sndBuffer = new uint8_t[periodsize*4*2]; if(!sndBuffer) { ErrorLogMessage("[ALSA Audio Plugin] sndBuffer allocation error."); return 1; } sndBufferPtr = sndBuffer; InfoLogMessage("[ALSA Audio Plugin] PCM device %s open at %d Hz %s, %d channels.", pcm_name, rate, snd_pcm_format_name(format), channels); return 0; }
bool QAudioOutputPrivate::open() { if(opened) return true; #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif timeStamp.restart(); elapsedTimeOffset = 0; int dir; int err = 0; int count=0; unsigned int freakuency=settings.frequency(); if (!settings.isValid()) { qWarning("QAudioOutput: open error, invalid format."); } else if (settings.sampleRate() <= 0) { qWarning("QAudioOutput: open error, invalid sample rate (%d).", settings.sampleRate()); } else { err = -1; } if (err == 0) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit errorChanged(errorState); return false; } QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) if (devices.size() > 0) dev = QLatin1String(devices.first()); else return false; #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(m_device); #else int idx = 0; char *name; QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData()); while(snd_card_get_name(idx,&name) == 0) { if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } // Step 1: try and open the device while((count < 5) && (err < 0)) { err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); if(err < 0) count++; } if (( err < 0)||(handle == 0)) { errorState = QAudio::OpenError; emit errorChanged(errorState); deviceState = QAudio::StoppedState; return false; } snd_pcm_nonblock( handle, 0 ); // Step 2: Set the desired HW parameters. snd_pcm_hw_params_alloca( &hwparams ); bool fatal = false; QString errMessage; unsigned int chunks = 8; err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_any: err = %1").arg(err); } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_access: err = %1").arg(err); } } if ( !fatal ) { err = setFormat(); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_format: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err); } } if ( !fatal ) { unsigned int maxBufferTime = 0; unsigned int minBufferTime = 0; unsigned int maxPeriodTime = 0; unsigned int minPeriodTime = 0; err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err); } else { if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) { #ifdef DEBUG_AUDIO qDebug()<<"defaults out of range"; qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime; #endif period_time = minPeriodTime; if (period_time*4 <= maxBufferTime) { // Use 4 periods if possible buffer_time = period_time*4; chunks = 4; } else if (period_time*2 <= maxBufferTime) { // Use 2 periods if possible buffer_time = period_time*2; chunks = 2; } else { qWarning()<<"QAudioOutput: alsa only supports single period!"; fatal = true; } #ifdef DEBUG_AUDIO qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time; #endif } } } if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params: err = %1").arg(err); } } if( err < 0) { qWarning()<<errMessage; errorState = QAudio::OpenError; emit errorChanged(errorState); deviceState = QAudio::StoppedState; return false; } snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames); buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames); snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir); period_size = snd_pcm_frames_to_bytes(handle,period_frames); snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); // Step 3: Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle, swparams); snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames); snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames); snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames); snd_pcm_sw_params(handle, swparams); // Step 4: Prepare audio if(audioBuffer == 0) audioBuffer = new char[snd_pcm_frames_to_bytes(handle,buffer_frames)]; snd_pcm_prepare( handle ); snd_pcm_start(handle); // Step 5: Setup callback and timer fallback snd_async_add_pcm_handler(&ahandler, handle, async_callback, this); bytesAvailable = bytesFree(); // Step 6: Start audio processing timer->start(period_time/1000); clockStamp.restart(); timeStamp.restart(); elapsedTimeOffset = 0; errorState = QAudio::NoError; totalTimeValue = 0; opened = true; return true; }
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) { int err, dir=0; unsigned int buffer_time; unsigned int period_time; unsigned int rrate; unsigned int rchannels; /* 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 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 = set_hwformat(handle, params); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return err; } /* set the count of channels */ rchannels = channels; err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels); if (err < 0) { printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err)); return err; } if (rchannels != channels) { printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels); num_channels = rchannels; } /* 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("WARNING: Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate); sample_rate = rrate; } /* set the buffer time */ buffer_time = 1000000*(uint64_t)period*nperiods/rate; 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", 1000000*period*nperiods/rate, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size ); if (err < 0) { printf("Unable to get buffer size back: %s\n", snd_strerror(err)); return err; } if( real_buffer_size != nperiods * period ) { printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size ); } /* set the period time */ period_time = 1000000*(uint64_t)period/rate; 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", 1000000*period/rate, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL ); if (err < 0) { printf("Unable to get period size back: %s\n", snd_strerror(err)); return err; } if( real_period_size != period ) { printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_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; }
bool CAESinkALSA::InitializeHW(AEAudioFormat &format) { snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_alloca(&hw_params); memset(hw_params, 0, snd_pcm_hw_params_sizeof()); snd_pcm_hw_params_any(m_pcm, hw_params); snd_pcm_hw_params_set_access(m_pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); unsigned int sampleRate = format.m_sampleRate; unsigned int channelCount = format.m_channelLayout.Count(); snd_pcm_hw_params_set_rate_near (m_pcm, hw_params, &sampleRate, NULL); snd_pcm_hw_params_set_channels_near(m_pcm, hw_params, &channelCount); /* ensure we opened X channels or more */ if (format.m_channelLayout.Count() > channelCount) { CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Unable to open the required number of channels"); } /* update the channelLayout to what we managed to open */ format.m_channelLayout.Reset(); for (unsigned int i = 0; i < channelCount; ++i) format.m_channelLayout += ALSAChannelMap[i]; snd_pcm_format_t fmt = AEFormatToALSAFormat(format.m_dataFormat); if (fmt == SND_PCM_FORMAT_UNKNOWN) { /* if we dont support the requested format, fallback to float */ format.m_dataFormat = AE_FMT_FLOAT; fmt = SND_PCM_FORMAT_FLOAT; } /* try the data format */ if (snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0) { /* if the chosen format is not supported, try each one in decending order */ CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Your hardware does not support %s, trying other formats", CAEUtil::DataFormatToStr(format.m_dataFormat)); for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1)) { if (AE_IS_RAW(i) || i == AE_FMT_MAX) continue; if (m_passthrough && i != AE_FMT_S16BE && i != AE_FMT_S16LE) continue; fmt = AEFormatToALSAFormat(i); if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0) { fmt = SND_PCM_FORMAT_UNKNOWN; continue; } int fmtBits = CAEUtil::DataFormatToBits(i); int bits = snd_pcm_hw_params_get_sbits(hw_params); if (bits != fmtBits) { /* if we opened in 32bit and only have 24bits, pack into 24 */ if (fmtBits == 32 && bits == 24) i = AE_FMT_S24NE4; else continue; } /* record that the format fell back to X */ format.m_dataFormat = i; CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Using data format %s", CAEUtil::DataFormatToStr(format.m_dataFormat)); break; } /* if we failed to find a valid output format */ if (fmt == SND_PCM_FORMAT_UNKNOWN) { CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Unable to find a suitable output format"); return false; } } snd_pcm_uframes_t periodSize, bufferSize; snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL); /* We want to make sure, that we have max 200 ms Buffer with a periodSize of approx 50 ms. Choosing a higher bufferSize will cause problems with menu sounds. Buffer will be increased after those are fixed. */ periodSize = std::min(periodSize, (snd_pcm_uframes_t) sampleRate / 20); bufferSize = std::min(bufferSize, (snd_pcm_uframes_t) sampleRate / 5); /* According to upstream we should set buffer size first - so make sure it is always at least 4x period size to not get underruns (some systems seem to have issues with only 2 periods) */ periodSize = std::min(periodSize, bufferSize / 4); CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, bufferSize %lu", periodSize, bufferSize); snd_pcm_hw_params_t *hw_params_copy; snd_pcm_hw_params_alloca(&hw_params_copy); snd_pcm_hw_params_copy(hw_params_copy, hw_params); // copy what we have and is already working // first trying bufferSize, PeriodSize // for more info see here: // http://mailman.alsa-project.org/pipermail/alsa-devel/2009-September/021069.html // the last three tries are done as within pulseaudio // backup periodSize and bufferSize first. Restore them after every failed try snd_pcm_uframes_t periodSizeTemp, bufferSizeTemp; periodSizeTemp = periodSize; bufferSizeTemp = bufferSize; if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0 || snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0 || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { bufferSize = bufferSizeTemp; periodSize = periodSizeTemp; // retry with PeriodSize, bufferSize snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy if (snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0 || snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0 || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { // try only periodSize periodSize = periodSizeTemp; snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy if(snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0 || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { // try only BufferSize bufferSize = bufferSizeTemp; snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restory working copy if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0 || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { // set default that Alsa would choose CLog::Log(LOGWARNING, "CAESinkAlsa::IntializeHW - Using default alsa values - set failed"); if (snd_pcm_hw_params(m_pcm, hw_params) != 0) { CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Could not init a valid sink"); return false; } } } // reread values when alsa default was kept snd_pcm_get_params(m_pcm, &bufferSize, &periodSize); } } CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize); /* set the format parameters */ format.m_sampleRate = sampleRate; format.m_frames = periodSize; format.m_frameSamples = periodSize * format.m_channelLayout.Count(); format.m_frameSize = snd_pcm_frames_to_bytes(m_pcm, 1); m_bufferSize = (unsigned int)bufferSize; m_timeout = std::ceil((double)(bufferSize * 1000) / (double)sampleRate); CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Setting timeout to %d ms", m_timeout); return true; }
/*---------------------------------------------------------------- TIesrFA_ALSA_open Try to open an ALSA audio PCM channel. ----------------------------------------------------------------*/ TIesrFA_ALSA_Error_t TIesrFA_ALSA_open( TIesrFA_t * const aTIesrFAInstance ) { int rtnStatus; int openSuccess = 0; snd_pcm_uframes_t numSamples; snd_pcm_hw_params_t *hw_params = 0; snd_pcm_sw_params_t *sw_params = 0; TIesrFA_ALSA_t * const ALSAData = (TIesrFA_ALSA_t * const) aTIesrFAInstance->impl_data; /* Try to open a handle to the ALSA pcm in blocking mode. */ rtnStatus = snd_pcm_open( &ALSAData->alsa_handle, aTIesrFAInstance->channel_name, SND_PCM_STREAM_CAPTURE, 0 ); if( rtnStatus < 0 ) goto openExit; /* Set up the information for recording from the audio channelport. This will include data specified by the user, such as data in aTIesrFAInstance->encoding, etc. If setup fails, then the audio channel should be shut down and failure reported. */ /* Setup hardware parameters of the ALSA pcm */ rtnStatus = snd_pcm_hw_params_malloc( &hw_params ); if( rtnStatus < 0 ) goto openExit; rtnStatus = snd_pcm_hw_params_any( ALSAData->alsa_handle, hw_params ); if( rtnStatus < 0 ) goto openExit; /* There will only be a single channel */ rtnStatus = snd_pcm_hw_params_set_channels( ALSAData->alsa_handle, hw_params, 1 ); if( rtnStatus < 0 ) goto openExit; /* Even though only one channel, must specify type of read. */ rtnStatus = snd_pcm_hw_params_set_access( ALSAData->alsa_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); if( rtnStatus < 0 ) goto openExit; /* Format type - only 16 bit linear for now */ rtnStatus = snd_pcm_hw_params_set_format( ALSAData->alsa_handle, hw_params, SND_PCM_FORMAT_S16 ); if( rtnStatus < 0 ) goto openExit; /* Set sample rate, it must be exactly supported */ rtnStatus = snd_pcm_hw_params_set_rate( ALSAData->alsa_handle, hw_params, aTIesrFAInstance->sample_rate, 0 ); if( rtnStatus < 0 ) goto openExit; /* Size of ALSA PCM ring buffer is set to approximately the desired number of multiples of read_samples in the buffer */ numSamples = aTIesrFAInstance->num_audio_buffer_frames * ALSAData->read_samples; rtnStatus = snd_pcm_hw_params_set_buffer_size_near( ALSAData->alsa_handle, hw_params, &numSamples ); if( rtnStatus < 0 ) goto openExit; /* Set the hardware parameters in the PCM*/ rtnStatus = snd_pcm_hw_params( ALSAData->alsa_handle, hw_params ); if( rtnStatus < 0 ) goto openExit; /* Set software parameters to interrupt at the end of an audio buffer number of samples and to start-up manually */ rtnStatus = snd_pcm_sw_params_malloc( &sw_params ); if( rtnStatus < 0 ) goto openExit; rtnStatus = snd_pcm_sw_params_current( ALSAData->alsa_handle, sw_params ); if( rtnStatus < 0 ) goto openExit; /* Number of samples needed in PCM buffer prior to interrupt */ rtnStatus = snd_pcm_sw_params_set_avail_min( ALSAData->alsa_handle, sw_params, ALSAData->read_samples ); if( rtnStatus < 0 ) goto openExit; /* Set start threshold so startup is done manually */ rtnStatus = snd_pcm_sw_params_set_start_threshold( ALSAData->alsa_handle, sw_params, ULONG_MAX ); if( rtnStatus < 0 ) goto openExit; /* Channel opened successfully */ openSuccess = 1; openExit: if( hw_params != NULL ) snd_pcm_hw_params_free( hw_params ); if( sw_params != NULL ) snd_pcm_sw_params_free( sw_params ); if( openSuccess ) return TIesrFA_ALSAErrNone; return TIesrFA_ALSAErrFail; }