Exemple #1
0
    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( &params );
    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(&params);

	/* 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;
}
Exemple #4
0
bool QAudioInputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
    clockStamp.restart();
    timeStamp.restart();
    elapsedTimeOffset = 0;

    int dir;
    int err = 0;
    int count=0;
    unsigned int freakuency=settings.frequency();

    if (!settings.isValid()) {
        qWarning("QAudioOutput: open error, invalid format.");
    } else if (settings.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();
}
Exemple #6
0
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;
}
Exemple #7
0
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 (&params);

  /* 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;
  }
}
Exemple #9
0
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(&params);

  /* 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;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
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(&params2);

  /* 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(&params);

  /* 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;
}
Exemple #14
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;
}
Exemple #15
0
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;
}
Exemple #16
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,
					&params.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;
}
Exemple #17
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;
    }
  }

  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;
}
Exemple #18
0
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);
}
Exemple #19
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(&params);
 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;
}
Exemple #20
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;
}
Exemple #21
0
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);
}
Exemple #22
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;
}
Exemple #23
0
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;
}
Exemple #24
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(&params);
		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]);
		}
	}
}
Exemple #25
0
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);
}
Exemple #26
0
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;
}
Exemple #27
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(&params);

   /* 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;
}
Exemple #30
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);
	}