void PCMThread::init() { snd_pcm_t* pcm_handle; snd_pcm_hw_params_t* hwparams; snd_pcm_uframes_t buffersize_return; unsigned int tmp; int err; std::unique_ptr<PCMHandle> spPCMHandle {new PCMHandle {spSettings_->pcmName_, SND_PCM_STREAM_CAPTURE}}; QObject::connect (spPCMHandle.get(), &PCMThread::PCMHandle::sigDebug, this, &PCMThread::slotDebug); snd_pcm_hw_params_alloca (&hwparams); if ( (err = snd_pcm_hw_params_any (*spPCMHandle, hwparams)) < 0) throw std::runtime_error (snd_strerror (err)); if ( (err = snd_pcm_hw_params_set_access (*spPCMHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) throw std::runtime_error (snd_strerror (err)); if ( (err = snd_pcm_hw_params_set_format (*spPCMHandle, hwparams, SND_PCM_FORMAT_FLOAT)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->rate_; if ( (err = snd_pcm_hw_params_set_rate_near (*spPCMHandle, hwparams, &tmp, 0)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->channels_; if ( (err = snd_pcm_hw_params_set_channels (*spPCMHandle, hwparams, tmp)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->periods_; if ( (err = snd_pcm_hw_params_set_periods (*spPCMHandle, hwparams, tmp, 0)) < 0) throw std::runtime_error (snd_strerror (err)); buffersize_return = spSettings_->periodSize_ * spSettings_->periods_; if ( (err = snd_pcm_hw_params_set_buffer_size_near (*spPCMHandle, hwparams, &buffersize_return)) < 0) throw std::runtime_error (snd_strerror (err)); if (buffersize_return != static_cast<snd_pcm_uframes_t> (spSettings_->periodSize_ * spSettings_->periods_)) { DebugHelper dbgHelper; dbgHelper << "Period size " << spSettings_->periodSize_ << " not available, using " << buffersize_return / spSettings_->periods_; emit sigDebug (dbgHelper.string()); periodSize_ = buffersize_return / spSettings_->periods_; } else { periodSize_ = spSettings_->periodSize_; } if ( (err = snd_pcm_hw_params (*spPCMHandle, hwparams)) < 0) throw std::runtime_error (snd_strerror (err)); spPCMHandle_ = std::move (spPCMHandle); emit sigDebug ("Initialized : " + QString::fromStdString (spSettings_->pcmName_)); }
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const { // Set nearest to closest settings that do work. // See if what is in settings will work (return value). int err = 0; snd_pcm_t* handle; snd_pcm_hw_params_t *params; QString dev = device; 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) dev = QLatin1String(devices.first().constData()); #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = device; #else int idx = 0; char *name; QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1); while(snd_card_get_name(idx,&name) == 0) { if(shortName.compare(QLatin1String(name)) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); } else { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); } if(err < 0) { handle = 0; return false; } bool testChannel = false; bool testCodec = false; bool testFreq = false; bool testType = false; bool testSize = false; int dir = 0; snd_pcm_nonblock( handle, 0 ); snd_pcm_hw_params_alloca( ¶ms ); snd_pcm_hw_params_any( handle, params ); // set the values! snd_pcm_hw_params_set_channels(handle,params,format.channels()); snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); err = -1; switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } // For now, just accept only audio/pcm codec if(!format.codec().startsWith(QLatin1String("audio/pcm"))) { err=-1; } else testCodec = true; if(err>=0 && format.channels() != -1) { err = snd_pcm_hw_params_test_channels(handle,params,format.channels()); if(err>=0) err = snd_pcm_hw_params_set_channels(handle,params,format.channels()); if(err>=0) testChannel = true; } if(err>=0 && format.frequency() != -1) { err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0); if(err>=0) err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); if(err>=0) testFreq = true; } if((err>=0 && format.sampleSize() != -1) && (format.sampleType() != QAudioFormat::Unknown)) { switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } if(err>=0) { testSize = true; testType = true; } } if(err>=0) err = snd_pcm_hw_params(handle, params); if(err == 0) { // settings work // close() if(handle) snd_pcm_close(handle); return true; } if(handle) snd_pcm_close(handle); return false; }
/* setup alsa data format and buffer geometry */ static inline int alsa_set_hwparams(ao_device *device, ao_sample_format *format) { ao_alsa_internal *internal = (ao_alsa_internal *) device->internal; snd_pcm_hw_params_t *params; int err; unsigned int rate = internal->sample_rate = format->rate; /* allocate the hardware parameter structure */ snd_pcm_hw_params_alloca(¶ms); /* fetch all possible hardware parameters */ err = snd_pcm_hw_params_any(internal->pcm_handle, params); if (err < 0){ adebug("snd_pcm_hw_params_any() failed.\n" " Device exists but no matching hardware?\n"); return err; } /* set the access type */ err = snd_pcm_hw_params_set_access(internal->pcm_handle, params, internal->access_mask); if (err < 0){ adebug("snd_pcm_hw_params_set_access() failed.\n"); return err; } /* set the sample bitformat */ err = snd_pcm_hw_params_set_format(internal->pcm_handle, params, internal->bitformat); if (err < 0){ /* the device may support a greater bit-depth than the one requested. */ switch(internal->bitformat){ case SND_PCM_FORMAT_U8: if (!snd_pcm_hw_params_set_format(internal->pcm_handle, params, SND_PCM_FORMAT_S16)){ adebug("snd_pcm_hw_params_set_format() unable to open %d bit playback.\n",format->bits); adebug("snd_pcm_hw_params_set_format() using 16 bit playback instead.\n"); format->bits = 16; break; } case SND_PCM_FORMAT_S16: if (!snd_pcm_hw_params_set_format(internal->pcm_handle, params, SND_PCM_FORMAT_S24)){ adebug("snd_pcm_hw_params_set_format() unable to open %d bit playback.\n",format->bits); adebug("snd_pcm_hw_params_set_format() using 24 bit playback instead.\n"); format->bits = 24; break; } case SND_PCM_FORMAT_S24: if (!snd_pcm_hw_params_set_format(internal->pcm_handle, params, SND_PCM_FORMAT_S32)){ adebug("snd_pcm_hw_params_set_format() unable to open %d bit playback.\n",format->bits); adebug("snd_pcm_hw_params_set_format() using 32 bit playback instead.\n"); format->bits = 32; break; } case SND_PCM_FORMAT_S32: adebug("snd_pcm_hw_params_set_format() failed.\n"); return err; } } /* set the number of channels */ err = snd_pcm_hw_params_set_channels(internal->pcm_handle, params, (unsigned int)device->output_channels); if (err < 0){ adebug("snd_pcm_hw_params_set_channels() failed.\n"); return err; } /* set the sample rate */ err = snd_pcm_hw_params_set_rate_near(internal->pcm_handle, params, &rate, 0); if (err < 0){ adebug("snd_pcm_hw_params_set_rate_near() failed.\n"); return err; } if (rate > 1.05 * format->rate || rate < 0.95 * format->rate) { awarn("sample rate %i not supported " "by the hardware, using %u\n", format->rate, rate); } /* set the time per hardware sample transfer */ if(internal->period_time==0) internal->period_time=internal->buffer_time/4; err = snd_pcm_hw_params_set_period_time_near(internal->pcm_handle, params, &(internal->period_time), 0); if (err < 0){ adebug("snd_pcm_hw_params_set_period_time_near() failed.\n"); return err; } /* set the length of the hardware sample buffer in microseconds */ /* some plug devices have very high minimum periods; don't allow a buffer size small enough that it's ~ guaranteed to skip */ if(internal->buffer_time<internal->period_time*3) internal->buffer_time=internal->period_time*3; err = snd_pcm_hw_params_set_buffer_time_near(internal->pcm_handle, params, &(internal->buffer_time), 0); if (err < 0){ adebug("snd_pcm_hw_params_set_buffer_time_near() failed.\n"); return err; } /* commit the params structure to the hardware via ALSA */ err = snd_pcm_hw_params(internal->pcm_handle, params); if (err < 0){ adebug("snd_pcm_hw_params() failed.\n"); return err; } /* save the period size in frames for posterity */ err = snd_pcm_hw_params_get_period_size(params, &(internal->period_size), 0); if (err < 0){ adebug("snd_pcm_hw_params_get_period_size() failed.\n"); return err; } return 1; }
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.frequency() <= 0) { qWarning("QAudioOutput: open error, invalid sample rate (%d).", settings.frequency()); } else { err = -1; } if (err == 0) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; 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) dev = QLatin1String(devices.first()); #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; }
// // Set up both the audio and video capturing on the card // void an_configure_capture_card( void ) { struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format fmt; sys_config info; int input; u32 pix_fmt; dvb_config_get( &info ); CLEAR(cropcap); CLEAR(crop); CLEAR(fmt); m_width = PAL_WIDTH_CAPTURE; m_height = PAL_HEIGHT_CAPTURE; // Set the cropping, ignore any errors cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(m_i_fd, VIDIOC_CROPCAP, &cropcap)==0) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; /* reset to default */ ioctl(m_i_fd, VIDIOC_S_CROP, &crop); } // // Analogue Video capture // pix_fmt = V4L2_PIX_FMT_YUV420; m_sws = NULL; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = m_width; fmt.fmt.pix.height = m_height; fmt.fmt.pix.pixelformat = pix_fmt; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0) { an_set_image_size( AV_PIX_FMT_YUV420P ); } else { pix_fmt = V4L2_PIX_FMT_YUYV; // capture format fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = m_width; fmt.fmt.pix.height = m_height; fmt.fmt.pix.pixelformat = pix_fmt; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0) { // Format conversion will be required m_sws = sws_getContext( m_width, m_height, AV_PIX_FMT_YUYV422, m_width, m_height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL,NULL, NULL); an_set_image_size( AV_PIX_FMT_YUYV422 ); } else { logger("CAP ANALOGUE FORMAT NOT SUPPORTED"); } } if(ioctl(m_i_fd, VIDIOC_G_FMT, &fmt)<0 ) logger("can't get format"); // input = V4L2_INPUT_TYPE_CAMERA; input = info.video_capture_device_input; if( ioctl( m_i_fd, VIDIOC_S_INPUT, &input) < 0 ) { loggerf("CAP Error VIDIOC_S_INPUT %d",input); } /* v4l2_streamparm parm; memset(&parm,0,sizeof(v4l2_streamparm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm.parm.capture.capturemode = 0; parm.parm.capture.readbuffers = 0; if( ioctl( m_i_fd, VIDIOC_S_PARM, &parm) < 0 ) { loggerf("CAP Error VIDIOC_S_PARM"); } */ info.video_bitrate = calculate_video_bitrate(); // // Analogue sound capture // snd_pcm_hw_params_t *hw_params; if(snd_pcm_open(&m_audio_handle, "pulse", SND_PCM_STREAM_CAPTURE, 0)< 0 ) { loggerf("Unable to open sound device"); return; } unsigned int rate = 48000; int r; r = snd_pcm_hw_params_malloc(&hw_params); r = snd_pcm_hw_params_any(m_audio_handle, hw_params); r = snd_pcm_hw_params_set_access(m_audio_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); r = snd_pcm_hw_params_set_format(m_audio_handle, hw_params, SND_PCM_FORMAT_S16_LE); r = snd_pcm_hw_params_set_rate_near(m_audio_handle, hw_params, &rate, 0); r = snd_pcm_hw_params_set_channels(m_audio_handle, hw_params, 2); r = snd_pcm_hw_params(m_audio_handle, hw_params); snd_pcm_hw_params_free(hw_params); r = snd_pcm_prepare(m_audio_handle); an_init_codecs(); m_capturing = true; an_setup_video_capturing( m_i_fd ); an_setup_audio_capturing(); }
static int initalsa(char *filename) { snd_pcm_hw_params_t *hw_params; int err; if ((err = snd_pcm_open(&capture_handle, filename, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf(stderr, "cannot open audio device %s (%s)\n", filename, snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); return 0; } 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)); return 0; } if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16)) < 0) { fprintf(stderr, "cannot set sample format (%s)\n", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, 48000, 0)) < 0) { fprintf(stderr, "cannot set sample rate (%s)\n", snd_strerror(err)); return 0; } for(nbch=2;nbch>0;nbch--) { if (snd_pcm_hw_params_set_channels(capture_handle, hw_params, nbch)==0) break; } if (nbch ==0) { fprintf(stderr, "cannot set number of channels\n"); return 0; } if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) { fprintf(stderr, "cannot set parameters (%s)\n", snd_strerror(err)); return 0; } 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)); return 0; } return nbch; }
static int init_audio_device(common_data_t *p_common_data) { int ret; int dir = 0; unsigned int val; snd_pcm_hw_params_t *p_params; snd_pcm_uframes_t buffer_size; unsigned int buffer_time; unsigned int period_time; snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; size_t bits_per_sample; size_t bits_per_frame; ret = snd_pcm_open(&p_common_data->handle, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) { dbg_alsa("unable to open pcm device: %s\n", snd_strerror(ret)); return -1; } snd_pcm_hw_params_alloca(&p_params); snd_pcm_hw_params_any(p_common_data->handle, p_params); snd_pcm_hw_params_set_access(p_common_data->handle, p_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(p_common_data->handle, p_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(p_common_data->handle, p_params, 2); val = 44100; snd_pcm_hw_params_set_rate_near(p_common_data->handle, p_params, &val, &dir); snd_pcm_hw_params_get_buffer_time_max(p_params, &buffer_time, 0); // if (buffer_time > 500000) // buffer_time = 500000; // // period_time = buffer_time / 4; // // snd_pcm_hw_params_set_period_time_near(p_common_data->handle, p_params, &period_time, 0); // snd_pcm_hw_params_set_buffer_time_near(p_common_data->handle, p_params, &buffer_time, 0); p_common_data->period_size = 2048; snd_pcm_hw_params_set_period_size_near(p_common_data->handle, p_params, &p_common_data->period_size, &dir); ret = snd_pcm_hw_params(p_common_data->handle, p_params); if (ret < 0){ dbg_alsa("unable to set hw parameters: %s\n", snd_strerror(ret)); exit(1); } ret = snd_pcm_state(p_common_data->handle); dbg("state is %d\n", ret); snd_pcm_hw_params_get_period_size(p_params, &p_common_data->period_size, &dir); snd_pcm_hw_params_get_buffer_size(p_params, &buffer_size); if (p_common_data->period_size == buffer_size) { dbg_alsa("Can't use period size equal to buffer size (%lu == %lu)\n", p_common_data->period_size, buffer_size); } dbg("period size is : %lu frames\n", p_common_data->period_size); dbg("buffer size is : %lu frames\n", buffer_size); bits_per_sample = snd_pcm_format_physical_width(format); bits_per_frame = bits_per_sample * 2; p_common_data->chunk_bytes = p_common_data->period_size * bits_per_frame / 8; //g_buf = (msg_t *)malloc(sizeof(msg_t)+(char)p_common_data->chunk_bytes); dbg("sample rate is %d\n", val); dbg("bits_per_sample %d\n", bits_per_sample); dbg("bits_per_frame %d\n", bits_per_frame); dbg("chunk_bytes %d\n", p_common_data->chunk_bytes); dbg("PCM handle name = '%s'\n",snd_pcm_name(p_common_data->handle)); return 0; }
static int set_hwparams (GstAlsaSrc * alsa) { guint rrate; gint err; snd_pcm_hw_params_t *params; snd_pcm_hw_params_malloc (¶ms); /* 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 */ 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 if (alsa->buffer_time != -1) { /* set the buffer time */ CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params, &alsa->buffer_time, NULL), buffer_time); GST_DEBUG_OBJECT (alsa, "buffer time %u", alsa->buffer_time); } if (alsa->period_time != -1) { /* set the period time */ CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params, &alsa->period_time, NULL), period_time); GST_DEBUG_OBJECT (alsa, "period time %u", alsa->period_time); } /* write the parameters to device */ CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params); 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); snd_pcm_hw_params_free (params); return 0; /* ERRORS */ no_config: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Broken configuration for recording: 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 recording: %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 recording: %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 recording in mono mode.")); if ((alsa->channels) == 2) msg = g_strdup (_("Could not open device for recording in stereo mode.")); if ((alsa->channels) > 2) msg = g_strdup_printf (_ ("Could not open device for recording 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 recording: %s", alsa->rate, snd_strerror (err))); snd_pcm_hw_params_free (params); 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_time: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set buffer time %i for recording: %s", alsa->buffer_time, snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } buffer_size: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to get buffer size for recording: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } period_time: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set period time %i for recording: %s", alsa->period_time, 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 recording: %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 recording: %s", snd_strerror (err))); snd_pcm_hw_params_free (params); return err; } }
int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; /* Open PCM device for playback. */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 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_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; 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 buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); /* 5 seconds in microseconds divided by * period time */ loops = 5000000 / val; while (loops > 0) { loops--; rc = read(0, buffer, size); if (rc == 0) { fprintf(stderr, "end of file on input\n"); break; } else if (rc != size) { fprintf(stderr, "short read: read %d bytes\n", rc); } rc = snd_pcm_writei(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short write, write %d frames\n", rc); } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
bool CAESinkALSA::InitializeHW(const ALSAConfig &inconfig, ALSAConfig &outconfig) { 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 = inconfig.sampleRate; unsigned int channelCount = inconfig.channels; #if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) // alsa/kernel lies, so map everything to 44100 or 48000 switch(sampleRate) { case 11025: case 22050: case 88200: case 176400: sampleRate = 44100; break; case 8000: case 16000: case 24000: case 32000: case 96000: case 192000: case 384000: sampleRate = 48000; break; } #endif 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 (inconfig.channels > channelCount) { CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Unable to open the required number of channels"); } /* update outconfig */ outconfig.channels = channelCount; snd_pcm_format_t fmt = AEFormatToALSAFormat(inconfig.format); outconfig.format = inconfig.format; if (fmt == SND_PCM_FORMAT_UNKNOWN) { /* if we dont support the requested format, fallback to float */ fmt = SND_PCM_FORMAT_FLOAT; outconfig.format = AE_FMT_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(outconfig.format)); 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 */ outconfig.format = i; CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Using data format %s", CAEUtil::DataFormatToStr(outconfig.format)); 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; } } unsigned int periods; snd_pcm_uframes_t periodSize, bufferSize; snd_pcm_hw_params_get_periods_min(hw_params, &periods, NULL); snd_pcm_hw_params_get_period_size_min(hw_params, &periodSize, NULL); snd_pcm_hw_params_get_buffer_size_min(hw_params, &bufferSize); CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Min: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); snd_pcm_hw_params_get_periods_max(hw_params, &periods, NULL); snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL); snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Max: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, 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); #if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) // must be pot for pivos. bufferSize = CheckNP2(bufferSize); #endif /* 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); #if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) // must be pot for pivos. periodSize = CheckNP2(periodSize); #endif bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); periodSize = bufferSize / ALSA_PERIODS; periods = ALSA_PERIODS; CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Req: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, 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 // Make sure to not initialize too large to not cause underruns snd_pcm_uframes_t periodSizeMax = bufferSize / 3; if(snd_pcm_hw_params_set_period_size_max(m_pcm, hw_params_copy, &periodSizeMax, NULL) != 0) { snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: Failed to limit periodSize to %lu", periodSizeMax); } // 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 */ outconfig.sampleRate = sampleRate; outconfig.periodSize = periodSize; outconfig.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; }
static boolean tsmf_alsa_set_format(ITSMFAudioDevice* audio, uint32 sample_rate, uint32 channels, uint32 bits_per_sample) { int error; snd_pcm_uframes_t frames; snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio; if (!alsa->out_handle) return false; snd_pcm_drop(alsa->out_handle); alsa->actual_rate = alsa->source_rate = sample_rate; alsa->actual_channels = alsa->source_channels = channels; alsa->bytes_per_sample = bits_per_sample / 8; error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return false; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); frames = sample_rate; snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc"); return false; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, frames / 2); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d", sample_rate, channels, bits_per_sample); DEBUG_DVC("hardware buffer %d frames", (int)frames); if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_DVC("actual rate %d / channel %d is different " "from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } return true; }
int setparams_set(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_sw_params_t *swparams, const char *id) { int err; snd_pcm_uframes_t val; unsigned int sleep_min = 0; err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff); if (err < 0) { printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err)); return err; } tick_time_ok = 0; if (tick_time > 0) { int time, ttime; snd_pcm_hw_params_get_period_time(params, &time, NULL); snd_pcm_hw_params_get_tick_time(params, &ttime, NULL); if (time < ttime) { printf("Skipping to set minimal sleep: period time < tick time\n"); } else if (ttime <= 0) { printf("Skipping to set minimal sleep: tick time <= 0 (%i)\n", ttime); } else { sleep_min = tick_time / ttime; if (sleep_min <= 0) sleep_min = 1; err = snd_pcm_sw_params_set_sleep_min(handle, swparams, sleep_min); if (err < 0) { printf("Unable to set minimal sleep %i for %s: %s\n", sleep_min, id, snd_strerror(err)); return err; } tick_time_ok = sleep_min * ttime; } } if (!block) val = 4; else snd_pcm_hw_params_get_period_size(params, &val, NULL); if (tick_time_ok > 0) val = 16; err = snd_pcm_sw_params_set_avail_min(handle, swparams, val); if (err < 0) { printf("Unable to set avail min for %s: %s\n", id, snd_strerror(err)); return err; } val = !block ? 4 : 1; err = snd_pcm_sw_params_set_xfer_align(handle, swparams, val); if (err < 0) { printf("Unable to set transfer align for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params(handle, swparams); if (err < 0) { printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err)); return err; } return 0; }
int main() { long loops; int rc, rc2; int size; snd_pcm_t *handle; snd_pcm_t *handle2; snd_pcm_hw_params_t *params; snd_pcm_hw_params_t *params2; unsigned int val, val2; int dir, dir2; snd_pcm_uframes_t frames, frames2; char *buffer; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE | SND_PCM_NONBLOCK, 0); // 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); } /* Open PCM device for playback. */ rc2 = snd_pcm_open(&handle2, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc2 < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc2)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms2); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle2, params2); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle2, params2, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle2, params2, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle2, params2, 2); /* 44100 bits/second sampling rate (CD quality) */ val2 = 96000; snd_pcm_hw_params_set_rate_near(handle2, params2, &val2, &dir2); /* Set period size to 32 frames. */ frames2 = 8; snd_pcm_hw_params_set_period_size_near(handle2, params2, &frames2, &dir2); /* Write the parameters to the driver */ rc2 = snd_pcm_hw_params(handle2, params2); if (rc2 < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc2)); 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_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 96000; //val = 48000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 8; 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 buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); fprintf(stderr, "sizeof buffer = %d\n", (int)size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 50000000 / val; int cnt =0; //pthread_t *alsa_t = malloc(sizeof(pthread_t)*2); while (loops > 0) { fprintf(stderr, "called %d\n",cnt++); loops--; // pthread_create(&alsa_t[0], NULL, &record_one( handle, buffer, frames), NULL); // pthread_create(record_t, NULL, play_one(handle2, buffer, frames), NULL); record_one(handle, buffer, frames); play_one(handle2, buffer, frames); } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); // pthread_join(alsa_t[0], NULL); // pthread_join(play_t, NULL); 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; }
void ags_devout_alsa_init(AgsDevout *devout, GError **error) { static unsigned int period_time = 100000; static snd_pcm_format_t format = SND_PCM_FORMAT_S16; int rc; snd_pcm_t *handle; snd_pcm_hw_params_t *hwparams; unsigned int val; snd_pcm_uframes_t frames; unsigned int rate; unsigned int rrate; unsigned int channels; snd_pcm_uframes_t size; snd_pcm_sframes_t buffer_size; snd_pcm_sframes_t period_size; snd_pcm_sw_params_t *swparams; int period_event = 0; int err, dir; /* Open PCM device for playback. */ if ((err = snd_pcm_open(&handle, devout->out.alsa.device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); return; } snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); /* choose all parameters */ err = snd_pcm_hw_params_any(handle, hwparams); if (err < 0) { printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); return; } /* set hardware resampling */ err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 1); if (err < 0) { printf("Resampling setup failed for playback: %s\n", snd_strerror(err)); return; } /* set the interleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Access type not available for playback: %s\n", snd_strerror(err)); return; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, hwparams, format); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return; } /* set the count of channels */ channels = devout->dsp_channels; err = snd_pcm_hw_params_set_channels(handle, hwparams, channels); if (err < 0) { printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err)); return; } /* set the stream rate */ rate = devout->frequency; rrate = rate; err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0); if (err < 0) { printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); return; } if (rrate != rate) { printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); exit(-EINVAL); } /* set the buffer size */ size = devout->buffer_size; err = snd_pcm_hw_params_set_buffer_size(handle, hwparams, size); if (err < 0) { printf("Unable to set buffer size %i for playback: %s\n", size, snd_strerror(err)); return; } buffer_size = size; /* set the period time */ err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if (err < 0) { printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err)); return; } err = snd_pcm_hw_params_get_period_size(hwparams, &size, &dir); if (err < 0) { printf("Unable to get period size for playback: %s\n", snd_strerror(err)); return; } period_size = size; /* write the parameters to device */ err = snd_pcm_hw_params(handle, hwparams); if (err < 0) { printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); return; } /* get the current swparams */ err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err)); return; } /* start the transfer when the buffer is almost full: */ /* (buffer_size / avail_min) * avail_min */ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size); if (err < 0) { printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); return; } /* allow the transfer when at least period_size samples can be processed */ /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */ err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size); if (err < 0) { printf("Unable to set avail min for playback: %s\n", snd_strerror(err)); return; } /* write the parameters to the playback device */ err = snd_pcm_sw_params(handle, swparams); if (err < 0) { printf("Unable to set sw params for playback: %s\n", snd_strerror(err)); return; } /* */ devout->out.alsa.handle = handle; devout->delay_counter = 0; }
static int alsa_open (struct sound_params *sound_params) { snd_pcm_hw_params_t *hw_params; int err; unsigned int period_time; unsigned int buffer_time; snd_pcm_uframes_t chunk_frames; snd_pcm_uframes_t buffer_frames; char fmt_name[128]; switch (sound_params->fmt & SFMT_MASK_FORMAT) { case SFMT_S8: params.format = SND_PCM_FORMAT_S8; break; case SFMT_U8: params.format = SND_PCM_FORMAT_U8; break; case SFMT_S16: params.format = SND_PCM_FORMAT_S16; break; case SFMT_U16: params.format = SND_PCM_FORMAT_U16; break; case SFMT_S32: params.format = SND_PCM_FORMAT_S32; break; case SFMT_U32: params.format = SND_PCM_FORMAT_U32; break; default: error ("Unknown sample format: %s", sfmt_str(sound_params->fmt, fmt_name, sizeof(fmt_name))); params.format = SND_PCM_FORMAT_UNKNOWN; return 0; } if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { error ("Can't open audio: %s", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { error ("Can't allocate alsa hardware parameters structure: %s", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { error ("Can't initialize hardware parameters structure: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { error ("Can't set alsa access type: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_format (handle, hw_params, params.format)) < 0) { error ("Can't set sample format: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } params.rate = sound_params->rate; if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, ¶ms.rate, 0)) < 0) { error ("Can't set sample rate: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } logit ("Set rate to %u", params.rate); if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, sound_params->channels)) < 0) { error ("Can't set number of channels: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &buffer_time, 0)) < 0) { error ("Can't get maximum buffer time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if (buffer_time > BUFFER_MAX_USEC) buffer_time = BUFFER_MAX_USEC; period_time = buffer_time / 4; if ((err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &period_time, 0)) < 0) { error ("Can't set period time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_buffer_time_near(handle, hw_params, &buffer_time, 0)) < 0) { error ("Can't set buffer time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { error ("Can't set audio parameters: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } snd_pcm_hw_params_get_period_size (hw_params, &chunk_frames, 0); snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_frames); bytes_per_frame = sound_params->channels * sfmt_Bps(sound_params->fmt); logit ("Buffer time: %"PRIu64"us", (uint64_t) buffer_frames * 1000000 / params.rate); if (chunk_frames == buffer_frames) { error ("Can't use period equal to buffer size (%lu == %lu)", chunk_frames, buffer_frames); snd_pcm_hw_params_free (hw_params); return 0; } chunk_size = chunk_frames * bytes_per_frame; debug ("Chunk size: %d", chunk_size); snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare(handle)) < 0) { error ("Can't prepare audio interface for use: %s", snd_strerror(err)); return 0; } logit ("ALSA device opened"); params.channels = sound_params->channels; alsa_buf_fill = 0; return 1; }
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; } } unsigned int periods; snd_pcm_uframes_t periodSize, bufferSize; snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); periodSize = bufferSize / ALSA_PERIODS; periods = ALSA_PERIODS; CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); /* work on a copy of the hw params */ snd_pcm_hw_params_t *hw_params_copy; snd_pcm_hw_params_alloca(&hw_params_copy); /* try to set the buffer size then the period size */ snd_pcm_hw_params_copy(hw_params_copy, hw_params); snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { /* try to set the period size then the buffer size */ snd_pcm_hw_params_copy(hw_params_copy, hw_params); snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { /* try to just set the buffer size */ snd_pcm_hw_params_copy(hw_params_copy, hw_params); snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { /* try to just set the period size */ snd_pcm_hw_params_copy(hw_params_copy, hw_params); snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) { CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters"); return false; } } } } snd_pcm_hw_params_get_period_size(hw_params_copy, &periodSize, NULL); snd_pcm_hw_params_get_buffer_size(hw_params_copy, &bufferSize); CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, 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; }
main (int argc, char *argv[]) { int i; int err; short buf[128]; snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; int dir = 0; unsigned int rate = 16000; unsigned int channels = 1; if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 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 (playback_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 (playback_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 (playback_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 (playback_handle, hw_params, &rate, &dir)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, channels )) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (playback_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 (playback_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_writei (playback_handle, buf, 128)) != 128) { fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (err)); exit (1); } } snd_pcm_close (playback_handle); exit (0); }
/* 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)) < 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; }
cst_audiodev *audio_open_alsa(unsigned int sps, int channels) { cst_audiodev *ad; int err; /* alsa specific stuff */ snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *hwparams; snd_pcm_format_t format; /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); /* Open pcm device */ err = snd_pcm_open(&pcm_handle, pcm_dev_name, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { cst_errmsg("audio_open_alsa: failed to open audio device %s. %s\n", pcm_dev_name, snd_strerror(err)); return NULL; } /* Init hwparams with full configuration space */ err = snd_pcm_hw_params_any(pcm_handle, hwparams); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to get hardware parameters from audio device. %s\n", snd_strerror(err)); return NULL; } /* Set access mode */ err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set access mode. %s.\n", snd_strerror(err)); return NULL; } #ifdef WORDS_BIGENDIAN format = SND_PCM_FORMAT_S16_BE; #else format = SND_PCM_FORMAT_S16_LE; #endif /* Set sample format */ err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format); if (err <0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set format. %s.\n", snd_strerror(err)); return NULL; } /* Set sample rate */ err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, sps, 0); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set sample rate near %d. %s.\n", sps, snd_strerror(err)); return NULL; } /* Set number of channels */ assert(channels >0); err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set number of channels to %d. %s.\n", channels, snd_strerror(err)); return NULL; } /* Commit hardware parameters */ err = snd_pcm_hw_params(pcm_handle, hwparams); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set hw parameters. %s.\n", snd_strerror(err)); return NULL; } /* Make sure the device is ready to accept data */ assert(snd_pcm_state(pcm_handle) == SND_PCM_STATE_PREPARED); /* Write hardware parameters to audio device data structure */ ad = cst_alloc(cst_audiodev, 1); assert(ad != NULL); ad->sps = sps; ad->channels = channels; ad->platform_data = (void *) pcm_handle; return ad; }
static void *sound_play(void *args) { char path[256]; int samplerate; int err; snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; FILE *fp; db_msg("prepare play sound...\n"); if (script_fetch("hdmi", "sound_file", (int *)path, sizeof(path) / 4)) { db_warn("unknown sound file, use default\n"); strcpy(path, "/dragonboard/data/test48000.pcm"); } if (script_fetch("hdmi", "samplerate", &samplerate, 1)) { db_warn("unknown samplerate, use default #48000\n"); samplerate = 48000; } db_msg("samplerate #%d\n", samplerate); err = snd_pcm_open(&playback_handle, "hw:1,0", SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { db_error("cannot open audio device (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_malloc(&hw_params); if (err < 0) { db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_any(playback_handle, hw_params); if (err < 0) { db_error("cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE); if (err < 0) { db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, samplerate, 0); if (err < 0) { db_error("cannot set sample rate (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2); if (err < 0) { db_error("cannot set channel count (%s), err = %d\n", snd_strerror(err), err); pthread_exit((void *)-1); } err = snd_pcm_hw_params(playback_handle, hw_params); if (err < 0) { db_error("cannot set parameters (%s)\n", snd_strerror(err)); pthread_exit((void *)-1); } snd_pcm_hw_params_free(hw_params); db_msg("open test pcm file: %s\n", path); fp = fopen(path, "r"); if (fp == NULL) { db_error("cannot open test pcm file(%s)\n", strerror(errno)); pthread_exit((void *)-1); } db_msg("play it...\n"); while (1) { while (!feof(fp)) { if (sound_play_stop) { goto out; } err = fread(buf, 1, BUF_LEN, fp); if (err < 0) { db_warn("read test pcm failed(%s)\n", strerror(errno)); } err = snd_pcm_writei(playback_handle, buf, BUF_LEN/4); if (err < 0) { err = xrun_recovery(playback_handle, err); if (err < 0) { db_warn("write error: %s\n", snd_strerror(err)); } } if (err == -EBADFD) { db_warn("PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)\n"); } if (err == -EPIPE) { db_warn("an underrun occurred\n"); } if (err == -ESTRPIPE) { db_warn("a suspend event occurred (stream is suspended and waiting for an application recovery)\n"); } if (feof(fp)) { fseek(fp, 0L, SEEK_SET); } } } out: db_msg("play end...\n"); fclose(fp); snd_pcm_close(playback_handle); pthread_exit(0); }
input_module_t *alsa_open_module(module_param_t *params) { input_module_t *mod = calloc(1, sizeof(input_module_t)); im_alsa_state *s; module_param_t *current; char *device = "plughw:0,0"; /* default device */ int format = AFMT_S16_LE; int channels, rate; int use_metadata = 1; /* Default to on */ unsigned int buffered_time; snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; snd_pcm_hw_params_t *hwparams; int err; mod->type = ICES_INPUT_PCM; mod->subtype = INPUT_PCM_LE_16; mod->getdata = alsa_read; mod->handle_event = event_handler; mod->metadata_update = metadata_update; mod->internal = calloc(1, sizeof(im_alsa_state)); s = mod->internal; s->fd = NULL; /* Set it to something invalid, for now */ s->rate = 44100; /* Defaults */ s->channels = 2; thread_mutex_create(&s->metadatalock); current = params; while(current) { if(!strcmp(current->name, "rate")) s->rate = atoi(current->value); else if(!strcmp(current->name, "channels")) s->channels = atoi(current->value); else if(!strcmp(current->name, "device")) device = current->value; else if(!strcmp(current->name, "metadata")) use_metadata = atoi(current->value); else if(!strcmp(current->name, "metadatafilename")) ices_config->metadata_filename = current->value; else LOG_WARN1("Unknown parameter %s for alsa module", current->name); current = current->next; } snd_pcm_hw_params_alloca(&hwparams); if ((err = snd_pcm_open(&s->fd, device, stream, 0)) < 0) { LOG_ERROR2("Failed to open audio device %s: %s", device, snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_any(s->fd, hwparams)) < 0) { LOG_ERROR1("Failed to initialize hwparams: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_access(s->fd, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { LOG_ERROR1("Error setting access: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_format(s->fd, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) { LOG_ERROR1("Couldn't set sample format to SND_PCM_FORMAT_S16_LE: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_rate_near(s->fd, hwparams, &s->rate, 0)) < 0) { LOG_ERROR1("Error setting rate: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_channels(s->fd, hwparams, s->channels)) < 0) { LOG_ERROR1("Error setting channels: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_periods(s->fd, hwparams, 2, 0)) < 0) { LOG_ERROR1("Error setting periods: %s", snd_strerror(err)); goto fail; } buffered_time = 500000; if ((err = snd_pcm_hw_params_set_buffer_time_near(s->fd, hwparams, &buffered_time, 0)) < 0) { LOG_ERROR1("Error setting buffersize: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params(s->fd, hwparams)) < 0) { LOG_ERROR1("Error setting HW params: %s", snd_strerror(err)); goto fail; } /* We're done, and we didn't fail! */ LOG_INFO3("Opened audio device %s at %d channel(s), %d Hz", device, s->channels, s->rate); if(use_metadata) { if(ices_config->metadata_filename) thread_create("im_alsa-metadata", metadata_thread_signal, mod, 1); else thread_create("im_alsa-metadata", metadata_thread_stdin, mod, 1); LOG_INFO0("Started metadata update thread"); } return mod; fail: close_module(mod); /* safe, this checks for valid contents */ return NULL; }
void Float32ToNativeInt32( const float *src, int *dst, unsigned int numToConvert ) { const float *src0 = src; int *dst0 = dst; unsigned int count = numToConvert; if (count >= 4) { // vector -- requires 4+ samples ROUNDMODE_NEG_INF const __m128 vround = (const __m128) { 0.5f, 0.5f, 0.5f, 0.5f }; const __m128 vmin = (const __m128) { -2147483648.0f, -2147483648.0f, -2147483648.0f, -2147483648.0f }; const __m128 vmax = (const __m128) { kMaxFloat32, kMaxFloat32, kMaxFloat32, kMaxFloat32 }; const __m128 vscale = (const __m128) { 2147483648.0f, 2147483648.0f, 2147483648.0f, 2147483648.0f }; __m128 vf0; __m128i vi0; #define F32TOLE32(x) \ vf##x = _mm_mul_ps(vf##x, vscale); \ vf##x = _mm_add_ps(vf##x, vround); \ vf##x = _mm_max_ps(vf##x, vmin); \ vf##x = _mm_min_ps(vf##x, vmax); \ vi##x = _mm_cvtps_epi32(vf##x); \ int falign = (uintptr_t)src & 0xF; int ialign = (uintptr_t)dst & 0xF; if (falign != 0 || ialign != 0) { // do one unaligned conversion vf0 = _mm_loadu_ps(src); F32TOLE32(0) _mm_storeu_si128((__m128i *)dst, vi0); // and advance such that the destination ints are aligned unsigned int n = (16 - ialign) / 4; src += n; dst += n; count -= n; falign = (uintptr_t)src & 0xF; if (falign != 0) { // unaligned loads, aligned stores while (count >= 4) { vf0 = _mm_loadu_ps(src); F32TOLE32(0) _mm_store_si128((__m128i *)dst, vi0); src += 4; dst += 4; count -= 4; } goto VectorCleanup; } } while (count >= 4) { vf0 = _mm_load_ps(src); F32TOLE32(0) _mm_store_si128((__m128i *)dst, vi0); src += 4; dst += 4; count -= 4; } VectorCleanup: if (count > 0) { // unaligned cleanup -- just do one unaligned vector at the end src = src0 + numToConvert - 4; dst = dst0 + numToConvert - 4; vf0 = _mm_loadu_ps(src); F32TOLE32(0) _mm_storeu_si128((__m128i *)dst, vi0); } RESTORE_ROUNDMODE return; } // scalar for small numbers of samples if (count > 0) { double scale = 2147483648.0, round = 0.5, max32 = 2147483648.0 - 1.0 - 0.5, min32 = 0.; ROUNDMODE_NEG_INF while (count-- > 0) { double f0 = *src++; f0 = f0 * scale + round; int i0 = FloatToInt(f0, min32, max32); *dst++ = i0; } RESTORE_ROUNDMODE } } void NativeInt32ToFloat32( const int *src, float *dst, unsigned int numToConvert ) { const int *src0 = src; float *dst0 = dst; unsigned int count = numToConvert; if (count >= 4) { // vector -- requires 4+ samples #define LEI32TOF32(x) \ vf##x = _mm_cvtepi32_ps(vi##x); \ vf##x = _mm_mul_ps(vf##x, vscale); \ const __m128 vscale = (const __m128) { 1.0/2147483648.0f, 1.0/2147483648.0f, 1.0/2147483648.0f, 1.0/2147483648.0f }; __m128 vf0; __m128i vi0; int ialign = (uintptr_t)src & 0xF; int falign = (uintptr_t)dst & 0xF; if (falign != 0 || ialign != 0) { // do one unaligned conversion vi0 = _mm_loadu_si128((__m128i const *)src); LEI32TOF32(0) _mm_storeu_ps(dst, vf0); // and advance such that the destination floats are aligned unsigned int n = (16 - falign) / 4; src += n; dst += n; count -= n; ialign = (uintptr_t)src & 0xF; if (ialign != 0) { // unaligned loads, aligned stores while (count >= 4) { vi0 = _mm_loadu_si128((__m128i const *)src); LEI32TOF32(0) _mm_store_ps(dst, vf0); src += 4; dst += 4; count -= 4; } goto VectorCleanup; } } // aligned loads, aligned stores while (count >= 4) { vi0 = _mm_load_si128((__m128i const *)src); LEI32TOF32(0) _mm_store_ps(dst, vf0); src += 4; dst += 4; count -= 4; } VectorCleanup: if (count > 0) { // unaligned cleanup -- just do one unaligned vector at the end src = src0 + numToConvert - 4; dst = dst0 + numToConvert - 4; vi0 = _mm_loadu_si128((__m128i const *)src); LEI32TOF32(0) _mm_storeu_ps(dst, vf0); } return; } // scalar for small numbers of samples if (count > 0) { double scale = 1./2147483648.0f; while (count-- > 0) { int i = *src++; double f = (double)i * scale; *dst++ = f; } } } int alsa_set_hwparams(alsa_dev_t *dev, snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access) { unsigned int rrate; snd_pcm_uframes_t size; int err, dir; /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); return err; } /* set the interleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, access); if (err < 0) { printf("Access type not available for playback: %s\n", snd_strerror(err)); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, dev->format); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return err; } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, dev->channels); if (err < 0) { printf("Channels count (%d) not available for playbacks: %s\n", dev->channels, snd_strerror(err)); return err; } /* set the stream rate */ rrate = dev->rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); if (err < 0) { printf("Rate %d Hz not available for playback: %s\n", dev->rate, snd_strerror(err)); return err; } if (rrate != dev->rate) { printf("Rate doesn't match (requested %dHz, get %dHz)\n", dev->rate, rrate); return -EINVAL; } /* set the period size */ err = snd_pcm_hw_params_set_period_size(handle, params, dev->period_size, 0); if (err < 0) { printf("Unable to set period size %d for playback: %s\n", (int)dev->period_size, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_period_size(params, &size, &dir); if (err < 0) { printf("Unable to get period size for playback: %s\n", snd_strerror(err)); return err; } if (dev->period_size != size) { printf("Period size doesn't match (requested %d, got %d)\n", (int)dev->period_size, (int)size); return -EINVAL; } /* set the buffer size */ err = snd_pcm_hw_params_set_buffer_size(handle, params, dev->buffer_size); if (err < 0) { printf("Unable to set buffer size %d for playback: %s\n", (int)dev->buffer_size, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_buffer_size(params, &size); if (err < 0) { printf("Unable to get buffer size for playback: %s\n", snd_strerror(err)); return err; } if (size != (snd_pcm_uframes_t)dev->buffer_size) { printf("Buffer size doesn't match (requested %d, got %d)\n", (int)dev->buffer_size, (int)size); return -EINVAL; } /* 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; } int alsa_set_swparams(alsa_dev_t *dev, snd_pcm_t *handle, snd_pcm_sw_params_t *swparams) { int err; /* get the current swparams */ err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err)); return err; } /* allow the transfer when at least period_size samples can be processed */ /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */ err = snd_pcm_sw_params_set_avail_min(handle, swparams, dev->period_size); if (err < 0) { printf("Unable to set avail min for playback: %s\n", snd_strerror(err)); return err; } /* enable period events */ err = snd_pcm_sw_params_set_period_event(handle, swparams, 1); if (err < 0) { printf("Unable to set period event: %s\n", snd_strerror(err)); return err; } /* write the parameters to the playback device */ err = snd_pcm_sw_params(handle, swparams); if (err < 0) { printf("Unable to set sw params for playback: %s\n", snd_strerror(err)); return err; } return 0; }
// Initialize the BlockSound class BlockSound::BlockSound() { sample_size = 0; #ifdef __APPLE__ remaining = 0; UInt32 size = sizeof(device); if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, (void *)&device) != noErr) return; size = sizeof(format); if (AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyStreamFormat, &size, &format) != noErr) return; // Set up a format we like... format.mSampleRate = 44100.0; // 44.1kHz format.mChannelsPerFrame = 2; // stereo if (AudioDeviceSetProperty(device, NULL, 0, false, kAudioDevicePropertyStreamFormat, sizeof(format), &format) != noErr) return; // Check we got linear pcm - what to do if we did not ??? if (format.mFormatID != kAudioFormatLinearPCM) return; // Attach the callback and start the device # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (AudioDeviceCreateIOProcID(device, audio_cb, (void *)this, &audio_proc_id) != noErr) return; AudioDeviceStart(device, audio_proc_id); # else if (AudioDeviceAddIOProc(device, audio_cb, (void *)this) != noErr) return; AudioDeviceStart(device, audio_cb); # endif sample_size = (int)format.mSampleRate; #elif defined(WIN32) WAVEFORMATEX format; memset(&format, 0, sizeof(format)); format.cbSize = sizeof(format); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; format.nSamplesPerSec = 44100; format.nAvgBytesPerSec = 44100 * 4; format.nBlockAlign = 4; format.wBitsPerSample = 16; data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, format.nSamplesPerSec * 4); if (!data_handle) return; data_ptr = (LPSTR)GlobalLock(data_handle); header_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR)); if (!header_handle) return; header_ptr = (WAVEHDR *)GlobalLock(header_handle); header_ptr->lpData = data_ptr; header_ptr->dwFlags = 0; header_ptr->dwLoops = 0; if (waveOutOpen(&device, WAVE_MAPPER, &format, 0, 0, WAVE_ALLOWSYNC) != MMSYSERR_NOERROR) return; sample_size = format.nSamplesPerSec; #else # ifdef HAVE_ALSA_ASOUNDLIB_H handle = NULL; if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) >= 0) { // Initialize PCM sound stuff... snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 2); unsigned rate = 44100; int dir; snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); snd_pcm_uframes_t period = (int)rate; snd_pcm_hw_params_set_period_size_near(handle, params, &period, &dir); sample_size = rate; if (snd_pcm_hw_params(handle, params) < 0) { sample_size = 0; snd_pcm_close(handle); handle = NULL; } } # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ if (sample_size) { // Make an explosion sound by passing white noise through a low pass // filter with a decreasing frequency... sample_data = new short[2 * sample_size]; short *sample_ptr = sample_data; int max_sample = 2 * sample_size - 2; *sample_ptr++ = 0; *sample_ptr++ = 0; for (int j = max_sample; j > 0; j --, sample_ptr ++) { float freq = (float)j / (float)max_sample; float volume = 32767.0 * (0.5 * sqrt(freq) + 0.5); float sample = 0.0001 * ((rand() % 20001) - 10000); *sample_ptr = (int)(volume * freq * sample + (1.0 - freq) * sample_ptr[-2]); } } }
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); }
static int audio_configure(snd_pcm_t *device) { snd_pcm_hw_params_t *hw_params; int err; unsigned int sr = SAMPLE_RATE; err = snd_pcm_hw_params_malloc(&hw_params); if (err) { fprintf(stderr, "can't allocate hw_params: %s\n", snd_strerror(err)); return err; } err = snd_pcm_hw_params_any(device, hw_params); if (err) { fprintf(stderr, "can't initialize hw_params: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_access(device, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err) { fprintf(stderr, "can't set access mode: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_format(device, hw_params, SND_PCM_FORMAT_S16_LE); if (err) { fprintf(stderr, "can't set format: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_rate_near(device, hw_params, &sr, 0); if (err) { fprintf(stderr, "can't set samplerate: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_channels(device, hw_params, 1); if (err) { fprintf(stderr, "can't set channels: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_buffer_size(device, hw_params, BUFFER_SIZE); if (err) { fprintf(stderr, "can't set buffer size: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params_set_period_size(device, hw_params, PERIOD_SIZE, 0); if (err) { fprintf(stderr, "can't set period size: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } err = snd_pcm_hw_params(device, hw_params); if (err) { fprintf(stderr, "can't set hw params: %s\n", snd_strerror(err)); snd_pcm_hw_params_free(hw_params); return err; } snd_pcm_hw_params_free(hw_params); return 0; }
bool WaveRecorder::init(uint32_t samples_per_sec, uint32_t bits_per_sample, uint32_t channels, uint32_t frame_size) { const char* pcm_device = "default"; snd_pcm_format_t format; int err; _frame_size = frame_size; switch (bits_per_sample) { case 8: format = SND_PCM_FORMAT_S8; break; case 16: format = SND_PCM_FORMAT_S16_LE; break; default: return false; } if ((err = snd_pcm_open(&_pcm, pcm_device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { LOG_ERROR("cannot open audio record device %s %s", pcm_device, snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_malloc(&_hw_params)) < 0) { LOG_ERROR("cannot allocate hardware parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_malloc(&_sw_params)) < 0) { LOG_ERROR("cannot allocate software parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_any(_pcm, _hw_params)) < 0) { LOG_ERROR("cannot initialize hardware parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_rate_resample(_pcm, _hw_params, 1)) < 0) { LOG_ERROR("cannot set rate resample %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_access(_pcm, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { LOG_ERROR("cannot set access type %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_rate(_pcm, _hw_params, samples_per_sec, 0)) < 0) { LOG_ERROR("cannot set sample rate %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_channels(_pcm, _hw_params, channels)) < 0) { LOG_ERROR("cannot set channel count %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_format(_pcm, _hw_params, format)) < 0) { LOG_ERROR("cannot set sample format %s", snd_strerror(err)); return false; } int direction = 0; snd_pcm_uframes_t buffer_size = (samples_per_sec * 160 / 1000) / frame_size * frame_size; if ((err = snd_pcm_hw_params_set_buffer_size_near(_pcm, _hw_params, &buffer_size)) < 0) { LOG_ERROR("cannot set buffer size %s", snd_strerror(err)); return false; } snd_pcm_uframes_t period_size = frame_size; if ((err = snd_pcm_hw_params_set_period_size_near(_pcm, _hw_params, &period_size, &direction)) < 0) { LOG_ERROR("cannot set period size near %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params(_pcm, _hw_params)) < 0) { LOG_ERROR("cannot set parameters %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_current(_pcm, _sw_params)) < 0) { LOG_ERROR("cannot get current sw parameters %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_set_start_threshold(_pcm, _sw_params, frame_size)) < 0) { LOG_ERROR("cannot set start threshold %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params(_pcm, _sw_params)) < 0) { LOG_ERROR("cannot set sw parameters %s", snd_strerror(err)); return false; } struct pollfd pfd; if ((err = snd_pcm_poll_descriptors(_pcm, &pfd, 1)) < 0) { LOG_ERROR("cannot get poll ID %s", snd_strerror(err)); return false; } _event_trigger = new WaveRecorder::EventTrigger(*this, pfd.fd); _client.add_event_source(*_event_trigger); return true; }
/** * Create and initialize Alsa audio output device with given parameters. * * @param Parameters - optional parameters * @throws AudioOutputException if output device cannot be opened */ AudioOutputDeviceAlsa::AudioOutputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) { pcm_handle = NULL; stream = SND_PCM_STREAM_PLAYBACK; this->uiAlsaChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt(); this->uiSamplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt(); this->FragmentSize = ((DeviceCreationParameterInt*)Parameters["FRAGMENTSIZE"])->ValueAsInt(); uint Fragments = ((DeviceCreationParameterInt*)Parameters["FRAGMENTS"])->ValueAsInt(); String Card = ((DeviceCreationParameterString*)Parameters["CARD"])->ValueAsString(); dmsg(2,("Checking if hw parameters supported...\n")); if (HardwareParametersSupported(Card, uiAlsaChannels, uiSamplerate, Fragments, FragmentSize)) { pcm_name = "hw:" + Card; } else { fprintf(stderr, "Warning: your soundcard doesn't support chosen hardware parameters; "); fprintf(stderr, "trying to compensate support lack with plughw..."); fflush(stdout); pcm_name = "plughw:" + Card; } dmsg(2,("HW check completed.\n")); int err; snd_pcm_hw_params_alloca(&hwparams); // Allocate the snd_pcm_hw_params_t structure on the stack. /* 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.c_str(), stream, 0)) < 0) { throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err)); } if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { throw AudioOutputException(String("Error, cannot initialize hardware parameter structure: ") + snd_strerror(err)); } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { throw AudioOutputException(String("Error snd_pcm_hw_params_set_access: ") + snd_strerror(err)); } /* Set sample format */ #if WORDS_BIGENDIAN if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) #else // little endian if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) #endif { throw AudioOutputException(String("Error setting sample format: ") + snd_strerror(err)); } int dir = 0; /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if ALSA_MAJOR > 0 if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &uiSamplerate, &dir)) < 0) #else if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, uiSamplerate, &dir)) < 0) #endif { throw AudioOutputException(String("Error setting sample rate: ") + snd_strerror(err)); } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, uiAlsaChannels)) < 0) { throw AudioOutputException(String("Error setting number of channels: ") + snd_strerror(err)); } /* Set number of periods. Periods used to be called fragments. */ if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, Fragments, dir)) < 0) { throw AudioOutputException(String("Error setting number of periods: ") + snd_strerror(err)); } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) { throw AudioOutputException(String("Error setting buffersize: ") + snd_strerror(err)); } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { throw AudioOutputException(String("Error setting HW params: ") + snd_strerror(err)); } if (snd_pcm_sw_params_malloc(&swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_malloc: ") + snd_strerror(err)); } if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_current: ") + snd_strerror(err)); } if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_set_stop_threshold: ") + snd_strerror(err)); } if (snd_pcm_sw_params(pcm_handle, swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params: ") + snd_strerror(err)); } if ((err = snd_pcm_prepare(pcm_handle)) < 0) { throw AudioOutputException(String("Error snd_pcm_prepare: ") + snd_strerror(err)); } // allocate Alsa output buffer pAlsaOutputBuffer = new int16_t[uiAlsaChannels * FragmentSize]; // create audio channels for this audio device to which the sampler engines can write to for (int i = 0; i < uiAlsaChannels; i++) this->Channels.push_back(new AudioChannel(i, FragmentSize)); if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) { Play(); } }
int main(int argc, char **argv){ int i; int aver,val,val2; int16_t buf[BUFSIZE]; double d_buffer[BUFSIZE]; double pitch = 0.0; struct timespec before,after; struct pitch_tracker_params *settings; snd_pcm_uframes_t period_size = PERIOD_SIZE; //ALSA PCM configuration snd_pcm_t *handle; snd_pcm_hw_params_t *params; int dir,rc; snd_pcm_uframes_t frames; /* Open PCM device for 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); /* unsigned 16-bit format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate */ val = 44100; snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir); /* set size time*/ snd_pcm_hw_params_set_period_size_near(handle, params, &period_size , &dir); /* write configuration */ rc = snd_pcm_hw_params(handle,params); /*Display info*/ printf("PCM handle name = '%s'\n", snd_pcm_name(handle)); printf("PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(handle))); snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val); printf("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(params, &val); printf("format = '%s' (%s)\n", snd_pcm_format_name((snd_pcm_format_t)val), snd_pcm_format_description( (snd_pcm_format_t)val)); snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val); printf("subformat = '%s' (%s)\n", snd_pcm_subformat_name((snd_pcm_subformat_t)val), snd_pcm_subformat_description( (snd_pcm_subformat_t)val)); snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); settings = open_pitch_tracker(); while(1){ rc = snd_pcm_readi(handle, buf, frames); 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); } for( i = 0 ; i< BUFSIZE ; i++){ d_buffer[i] = (double) buf[i]; } pitch = compute_pitch(d_buffer, BUFSIZE, S16, settings ,ACCURACY); if( pitch != 0.0 ) printf("frequency -> %f\n",pitch); memset(buf,0,BUFSIZE); } close_pitch_tracker(&settings); snd_pcm_drain(handle); snd_pcm_close(handle); return 0; }
main (int argc, char *argv[]) { snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_sframes_t frames_to_deliver; int nfds; int err; struct pollfd *pfds; if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 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 (playback_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 (playback_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 (playback_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 (playback_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 (playback_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (playback_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_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 4096)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 0U)) < 0) { fprintf (stderr, "cannot set start mode (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_prepare (playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } while (1) { if ((err = snd_pcm_wait (playback_handle, 1000)) < 0) { fprintf (stderr, "poll failed (%s)\n", strerror (errno)); break; } if ((frames_to_deliver = snd_pcm_avail_update (playback_handle)) < 0) { if (frames_to_deliver == -EPIPE) { fprintf (stderr, "an xrun occured\n"); break; } else { fprintf (stderr, "unknown ALSA avail update return value (%d)\n", frames_to_deliver); break; } } frames_to_deliver = frames_to_deliver > 4096 ? 4096 : frames_to_deliver; if (playback_callback (frames_to_deliver) != frames_to_deliver) { fprintf (stderr, "playback callback failed\n"); break; } } snd_pcm_close (playback_handle); exit (0); }