ALSA(unsigned channels, unsigned samplerate, const std::string& device = "default") : runnable(true), pcm(nullptr), params(nullptr), fps(samplerate) { int rc = snd_pcm_open(&pcm, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { runnable = false; throw DeviceException(General::join("Unable to open PCM device ", snd_strerror(rc))); } snd_pcm_format_t fmt = type_to_format(T()); if (snd_pcm_hw_params_malloc(¶ms) < 0) { runnable = false; throw DeviceException("Failed to allocate memory."); } runnable = false; if ( (snd_pcm_hw_params_any(pcm, params) < 0) || (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) || (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) || (snd_pcm_hw_params_set_format(pcm, params, fmt) < 0) || (snd_pcm_hw_params_set_rate(pcm, params, samplerate, 0) < 0) || ((rc = snd_pcm_hw_params(pcm, params)) < 0) ) throw DeviceException(General::join("Unable to install HW params: ", snd_strerror(rc))); runnable = true; }
internal void hhxcb_init_alsa(hhxcb_context *context, hhxcb_sound_output *sound_output) { // NOTE: "hw:0,0" doesn't seem to work with alsa running on top of pulseaudio char *device = (char *)"default"; // char *device = (char *)"hw:0,0"; int err; snd_pcm_sframes_t frames; err = snd_output_stdio_attach(&context->alsa_log, stderr, 0); if ((err = snd_pcm_open(&context->handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_any(context->handle, hwparams); snd_pcm_hw_params_set_rate_resample(context->handle, hwparams, 0); snd_pcm_hw_params_set_access(context->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(context->handle, hwparams, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(context->handle, hwparams, 2); snd_pcm_hw_params_set_rate(context->handle, hwparams, sound_output->samples_per_second, 0); snd_pcm_hw_params_set_period_size(context->handle, hwparams, sound_output->samples_per_second / 60, 0); // NOTE: restricting this buffer size too much seems to crash the game sound_output->secondary_buffer_size = 48000 / 2; snd_pcm_hw_params_set_buffer_size(context->handle, hwparams, sound_output->secondary_buffer_size); snd_pcm_hw_params(context->handle, hwparams); snd_pcm_dump(context->handle, context->alsa_log); }
void initsound(int samplerate, int channels) { int dir, pcmrc; /* Open the PCM device in playback mode */ snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); /* Allocate parameters object and fill it with default values*/ snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(pcm_handle, params); /* Set parameters */ snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(pcm_handle, params, channels); snd_pcm_hw_params_set_rate(pcm_handle, params, samplerate, 0); /* Write parameters */ snd_pcm_hw_params(pcm_handle, params); /* Allocate buffer to hold single period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); buf = malloc(frames * channels * 2 * BUFFER_NUM); }
static int set_rate(Instance *pi, const char *value) { int rc; unsigned int rate = atoi(value); ALSAio_private *priv = (ALSAio_private *)pi; if (!priv->c.handle) { fprintf(stderr, "*** device is not open!\n"); return 1; } rc = snd_pcm_hw_params_set_rate(priv->c.handle, priv->c.hwparams, rate, 0); if (rc == 0) { fprintf(stderr, "rate set to %d\n", rate); priv->c.rate = rate; } else { fprintf(stderr, "*** error setting rate %d (%s)\n", rate, snd_strerror(rc)); } return rc; }
StackAudioDevice *stack_alsa_audio_device_create(const char *name, uint32_t channels, uint32_t sample_rate) { // Debug fprintf(stderr, "stack_alsa_audio_device_create(\"%s\", %u, %u) called\n", name, channels, sample_rate); // Allocate the new device StackAlsaAudioDevice *device = new StackAlsaAudioDevice(); device->stream = NULL; if (snd_pcm_open(&device->stream, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) != 0) { fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_open() failed\n"); return NULL; } // Get some initial hardware parameters snd_pcm_hw_params_t *hw_params = NULL; snd_pcm_hw_params_malloc(&hw_params); snd_pcm_hw_params_any(device->stream, hw_params); // Choose the correct sample rate if (snd_pcm_hw_params_set_rate(device->stream, hw_params, sample_rate, 0) < 0) { fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_rate() failed\n"); } // Set the correct number of channels if (snd_pcm_hw_params_set_channels(device->stream, hw_params, channels) < 0) { fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_channels() failed\n"); } // Set the format to 32-bit floating point, which is what Stack // uses internally if (snd_pcm_hw_params_set_format(device->stream, hw_params, SND_PCM_FORMAT_FLOAT_LE) < 0) { fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_format() failed\n"); } // Apply the hardware parameters to the device snd_pcm_hw_params(device->stream, hw_params); // Set up superclass STACK_AUDIO_DEVICE(device)->_class_name = "StackAlsaAudioDevice"; STACK_AUDIO_DEVICE(device)->channels = channels; STACK_AUDIO_DEVICE(device)->sample_rate = sample_rate; // Start the PCM stream if (snd_pcm_start(device->stream) < 0) { fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_start() failed\n"); } // Return the newly created device return STACK_AUDIO_DEVICE(device); }
static int setup_params(void) { snd_pcm_hw_params_t *hw; /* FIXME: more finer error checks */ snd_pcm_hw_params_alloca(&hw); snd_pcm_hw_params_any(pcm, hw); snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(pcm, hw, format); snd_pcm_hw_params_set_channels(pcm, hw, channels); snd_pcm_hw_params_set_rate(pcm, hw, rate, 0); snd_pcm_hw_params_set_period_size(pcm, hw, periodsize, 0); snd_pcm_hw_params_set_buffer_size(pcm, hw, bufsize); if (snd_pcm_hw_params(pcm, hw) < 0) { fprintf(stderr, "snd_pcm_hw_params error\n"); return 1; } return 0; }
int audio_drv_init(char const * const device) { unsigned int rate = 44100; int err; snd_pcm_hw_params_t *hw_params; if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) return -1; if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) return -2; if ((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0) return -3; if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) return -4; if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) return -5; if ((err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, rate, 0)) < 0) return -6; if ((err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2)) < 0) return -7; if ((err = snd_pcm_hw_params_set_period_size(playback_handle, hw_params, 2048, 0)) < 0) return -8; if ((err = snd_pcm_hw_params_set_periods(playback_handle, hw_params, 4, 0)) < 0) return -9; if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0) return -10; snd_pcm_hw_params_free(hw_params); if ((err = snd_pcm_prepare(playback_handle)) < 0) return -11; return 0; }
int AudioAlsa::setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access ) { int err, dir; // choose all parameters if( ( err = snd_pcm_hw_params_any( m_handle, m_hwParams ) ) < 0 ) { printf( "Broken configuration for playback: no configurations " "available: %s\n", snd_strerror( err ) ); return err; } // set the interleaved read/write format if( ( err = snd_pcm_hw_params_set_access( m_handle, m_hwParams, _access ) ) < 0 ) { printf( "Access type not available for playback: %s\n", snd_strerror( err ) ); return err; } // set the sample format if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams, SND_PCM_FORMAT_S16_LE ) ) < 0 ) { if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams, SND_PCM_FORMAT_S16_BE ) ) < 0 ) { printf( "Neither little- nor big-endian available for " "playback: %s\n", snd_strerror( err ) ); return err; } m_convertEndian = isLittleEndian(); } else { m_convertEndian = !isLittleEndian(); } // set the count of channels if( ( err = snd_pcm_hw_params_set_channels( m_handle, m_hwParams, _channels ) ) < 0 ) { printf( "Channel count (%i) not available for playbacks: %s\n" "(Does your soundcard not support surround?)\n", _channels, snd_strerror( err ) ); return err; } // set the sample rate if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams, sampleRate(), 0 ) ) < 0 ) { if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams, mixer()->baseSampleRate(), 0 ) ) < 0 ) { printf( "Could not set sample rate: %s\n", snd_strerror( err ) ); return err; } } m_periodSize = mixer()->framesPerPeriod(); m_bufferSize = m_periodSize * 8; dir = 0; err = snd_pcm_hw_params_set_period_size_near( m_handle, m_hwParams, &m_periodSize, &dir ); if( err < 0 ) { printf( "Unable to set period size %lu for playback: %s\n", m_periodSize, snd_strerror( err ) ); return err; } dir = 0; err = snd_pcm_hw_params_get_period_size( m_hwParams, &m_periodSize, &dir ); if( err < 0 ) { printf( "Unable to get period size for playback: %s\n", snd_strerror( err ) ); } dir = 0; err = snd_pcm_hw_params_set_buffer_size_near( m_handle, m_hwParams, &m_bufferSize ); if( err < 0 ) { printf( "Unable to set buffer size %lu for playback: %s\n", m_bufferSize, snd_strerror( err ) ); return ( err ); } err = snd_pcm_hw_params_get_buffer_size( m_hwParams, &m_bufferSize ); if( 2 * m_periodSize > m_bufferSize ) { printf( "buffer to small, could not use\n" ); return ( err ); } // write the parameters to device err = snd_pcm_hw_params( m_handle, m_hwParams ); if( err < 0 ) { printf( "Unable to set hw params for playback: %s\n", snd_strerror( err ) ); return ( err ); } return ( 0 ); // all ok }
static int laudio_alsa_open(void) { snd_pcm_hw_params_t *hw_params; snd_pcm_uframes_t bufsize; int ret; hw_params = NULL; ret = snd_pcm_open(&hdl, card_name, SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not open playback device: %s\n", snd_strerror(ret)); return -1; } /* HW params */ ret = snd_pcm_hw_params_malloc(&hw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not allocate hw params: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_any(hdl, hw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not retrieve hw params: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_set_access(hdl, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set access method: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_set_format(hdl, hw_params, SND_PCM_FORMAT_S16_LE); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set S16LE format: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_set_channels(hdl, hw_params, 2); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set stereo output: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_set_rate(hdl, hw_params, 44100, 0); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Hardware doesn't support 44.1 kHz: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufsize); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not get max buffer size: %s\n", snd_strerror(ret)); goto out_fail; } DPRINTF(E_DBG, L_LAUDIO, "Max buffer size is %lu samples\n", bufsize); ret = snd_pcm_hw_params_set_buffer_size_max(hdl, hw_params, &bufsize); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set buffer size to max: %s\n", snd_strerror(ret)); goto out_fail; } DPRINTF(E_DBG, L_LAUDIO, "Buffer size is %lu samples\n", bufsize); ret = snd_pcm_hw_params(hdl, hw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set hw params: %s\n", snd_strerror(ret)); goto out_fail; } snd_pcm_hw_params_free(hw_params); hw_params = NULL; pcm_pos = 0; pcm_last_error = 0; pcm_recovery = 0; pcm_buf_threshold = (bufsize / AIRTUNES_V2_PACKET_SAMPLES) * AIRTUNES_V2_PACKET_SAMPLES; ret = mixer_open(); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not open mixer\n"); goto out_fail; } update_status(LAUDIO_OPEN); return 0; out_fail: if (hw_params) snd_pcm_hw_params_free(hw_params); snd_pcm_close(hdl); hdl = NULL; return -1; }
static snd_pcm_uframes_t set_params(snd_pcm_t *handle, snd_pcm_stream_t stream) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t chunk_size = 0; snd_pcm_uframes_t start_threshold; unsigned period_time = 0; unsigned buffer_time = 0; size_t chunk_bytes = 0; int err; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for this PCM: no configurations available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Access type not available"); exit(EXIT_FAILURE); } printf("format = %s, channels = %d, rate = %d\n", snd_pcm_format_name(hwparams.format),hwparams.channels,hwparams.rate); //err = snd_pcm_hw_params_set_format(handle, params, hwparams.format); err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { printf("Sample format non available"); exit(EXIT_FAILURE); } //err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); err = snd_pcm_hw_params_set_channels(handle, params, 2); if (err < 0) { printf("Channels count non available"); exit(EXIT_FAILURE); } #if 0 //add by yjc 2012/08/21 err = set_audio_clk_freq(hwparams.rate); if (err < 0){ printf("set_audio_clk_freq fail..........\n"); exit(EXIT_FAILURE); } #endif err = snd_pcm_hw_params_set_rate(handle, params, hwparams.rate, 0); if (err < 0) { printf("Rate non available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); assert(err >= 0); if (buffer_time > 500000) buffer_time = 500000; period_time = buffer_time / 4; err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0); assert(err >= 0); err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); assert(err >= 0); err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to install hw params:"); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_period_size(params, &chunk_size, 0); snd_pcm_hw_params_get_buffer_size(params, &buffer_size); if (chunk_size == buffer_size) { printf("Can't use period equal to buffer size (%lu == %lu)", chunk_size, buffer_size); exit(EXIT_FAILURE); } snd_pcm_sw_params_current(handle, swparams); err = snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size); if(stream == SND_PCM_STREAM_PLAYBACK) start_threshold = (buffer_size / chunk_size) * chunk_size; else start_threshold = 1; err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); assert(err >= 0); err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, buffer_size); assert(err >= 0); if (snd_pcm_sw_params(handle, swparams) < 0) { printf("unable to install sw params:"); exit(EXIT_FAILURE); } //bits_per_sample = snd_pcm_format_physical_width(hwparams.format); bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); //bits_per_frame = bits_per_sample * hwparams.channels; bits_per_frame = bits_per_sample * 2; chunk_bytes = chunk_size * bits_per_frame / 8; printf("chunk_size = %d,chunk_bytes = %d,buffer_size = %d\n\n", (int)chunk_size,chunk_bytes,(int)buffer_size); return chunk_size; }
static void *alsa_thread_init(const char *device, unsigned rate, unsigned latency) { snd_pcm_uframes_t buffer_size; snd_pcm_format_t format; snd_pcm_hw_params_t *params = NULL; snd_pcm_sw_params_t *sw_params = NULL; const char *alsa_dev = device ? device : "default"; unsigned latency_usec = latency * 1000 / 2; unsigned channels = 2; unsigned periods = 4; alsa_thread_t *alsa = (alsa_thread_t*) calloc(1, sizeof(alsa_thread_t)); if (!alsa) return NULL; TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0)); TRY_ALSA(snd_pcm_hw_params_malloc(¶ms)); alsa->has_float = alsathread_find_float_format(alsa->pcm, params); format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16; TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params)); TRY_ALSA(snd_pcm_hw_params_set_access( alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED)); TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format)); TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels)); TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0)); TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near( alsa->pcm, params, &latency_usec, NULL)); TRY_ALSA(snd_pcm_hw_params_set_periods_near( alsa->pcm, params, &periods, NULL)); TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params)); /* Shouldn't have to bother with this, * but some drivers are apparently broken. */ if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL)) snd_pcm_hw_params_get_period_size_min( params, &alsa->period_frames, NULL); RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames); if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size)) snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size); RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size); alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size); alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames); TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params)); TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params)); TRY_ALSA(snd_pcm_sw_params_set_start_threshold( alsa->pcm, sw_params, buffer_size / 2)); TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params)); snd_pcm_hw_params_free(params); snd_pcm_sw_params_free(sw_params); alsa->fifo_lock = slock_new(); alsa->cond_lock = slock_new(); alsa->cond = scond_new(); alsa->buffer = fifo_new(alsa->buffer_size); if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer) goto error; alsa->worker_thread = sthread_create(alsa_worker_thread, alsa); if (!alsa->worker_thread) { RARCH_ERR("error initializing worker thread"); goto error; } return alsa; error: RARCH_ERR("ALSA: Failed to initialize...\n"); if (params) snd_pcm_hw_params_free(params); if (sw_params) snd_pcm_sw_params_free(sw_params); alsa_thread_free(alsa); return NULL; }
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const { // Set nearest to closest settings that do work. // See if what is in settings will work (return value). int err = 0; snd_pcm_t* handle; snd_pcm_hw_params_t *params; QString dev = device; QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(devices.first().constData()); #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = device; #else int idx = 0; char *name; QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1); while(snd_card_get_name(idx,&name) == 0) { if(shortName.compare(QLatin1String(name)) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); } else { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); } if(err < 0) { handle = 0; return false; } bool testChannel = false; bool testCodec = false; bool testFreq = false; bool testType = false; bool testSize = false; int dir = 0; snd_pcm_nonblock( handle, 0 ); snd_pcm_hw_params_alloca( ¶ms ); snd_pcm_hw_params_any( handle, params ); // set the values! snd_pcm_hw_params_set_channels(handle,params,format.channels()); snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); err = -1; switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } // For now, just accept only audio/pcm codec if(!format.codec().startsWith(QLatin1String("audio/pcm"))) { err=-1; } else testCodec = true; if(err>=0 && format.channels() != -1) { err = snd_pcm_hw_params_test_channels(handle,params,format.channels()); if(err>=0) err = snd_pcm_hw_params_set_channels(handle,params,format.channels()); if(err>=0) testChannel = true; } if(err>=0 && format.frequency() != -1) { err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0); if(err>=0) err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); if(err>=0) testFreq = true; } if((err>=0 && format.sampleSize() != -1) && (format.sampleType() != QAudioFormat::Unknown)) { switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } if(err>=0) { testSize = true; testType = true; } } if(err>=0) err = snd_pcm_hw_params(handle, params); if(err == 0) { // settings work // close() if(handle) snd_pcm_close(handle); return true; } if(handle) snd_pcm_close(handle); return false; }
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; }
bool AlsaRenderer::SetupHwParams() { snd_pcm_hw_params_t* params; /* allocate a hardware parameters object */ snd_pcm_hw_params_malloc(¶ms); /* choose all parameters */ snd_pcm_hw_params_any(m_PcmHandle, params); /* enable hardware resampling */ snd_pcm_hw_params_set_rate_resample(m_PcmHandle, params, m_Resample); /* set the interleaved read/write format */ snd_pcm_hw_params_set_access(m_PcmHandle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(m_PcmHandle, params, SND_PCM_FORMAT_S16_LE); /* set the count of channels */ snd_pcm_hw_params_get_channels_max(params, &m_Channels.max); snd_pcm_hw_params_get_channels_min(params, &m_Channels.min); if (m_Channels.val < m_Channels.min || m_Channels.val > m_Channels.max) m_Channels.val = m_Channels.min; snd_pcm_hw_params_set_channels(m_PcmHandle, params, m_Channels.val); /* set the stream rate */ snd_pcm_hw_params_get_rate_max(params, &m_SampleRate.max, &m_Dir); snd_pcm_hw_params_get_rate_min(params, &m_SampleRate.min, &m_Dir); if (m_SampleRate.val < m_SampleRate.min || m_SampleRate.val > m_SampleRate.max) m_SampleRate.val = m_SampleRate.min; printf("sample rate max:%d, min:%d, val:%d\n", m_SampleRate.max, m_SampleRate.min, m_SampleRate.val); snd_pcm_hw_params_set_rate(m_PcmHandle, params, m_SampleRate.val, m_Dir); /* we can set period and buffer by size or time */ /* by default we use "size" (count of frames) */ /* set how many frames in a buffer (a buffer cantains several periods) */ snd_pcm_hw_params_get_buffer_size_max(params, &m_BufferSize.max); snd_pcm_hw_params_get_buffer_size_min(params, &m_BufferSize.min); /* detect period time and buffer time range */ snd_pcm_hw_params_get_buffer_time_max(params, &m_BufferTime.max, &m_Dir); snd_pcm_hw_params_get_buffer_time_min(params, &m_BufferTime.min, &m_Dir); m_BufferTime.val = std::max(m_BufferTime.max / 2, m_BufferTime.min); //m_BufferTime.val = m_BufferTime.min + (m_BufferTime.max - m_BufferTime.min) /2; printf("buffer time max:%d, min:%d, val:%d\n", m_BufferTime.max, m_BufferTime.min, m_BufferTime.val); //(m_BufferTime.max > 120000) ? 120000 : m_BufferTime.max;//120000 snd_pcm_hw_params_set_buffer_time_near(m_PcmHandle, params, &m_BufferTime.val, &m_Dir); snd_pcm_hw_params_get_period_time_max(params, &m_PeriodTime.max, &m_Dir); snd_pcm_hw_params_get_period_time_min(params, &m_PeriodTime.min, &m_Dir); m_PeriodTime.val = m_BufferTime.val / 4; //m_PeriodTime.val = m_PeriodTime.min + (m_PeriodTime.max - m_PeriodTime.min) / 2; printf("period time max:%d, min:%d, val:%d\n", m_PeriodTime.max, m_PeriodTime.min, m_PeriodTime.val); snd_pcm_hw_params_set_period_time_near(m_PcmHandle, params, &m_PeriodTime.val, &m_Dir); int ret = snd_pcm_hw_params(m_PcmHandle, params); if (ret != 0) { snd_pcm_hw_params_free(params); return false; } // get period size again snd_pcm_hw_params_get_period_size(params, &m_PeriodSize.val, &m_Dir); snd_pcm_hw_params_get_buffer_size(params, &m_BufferSize.val); m_BitsPerSample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); m_FrameLength = (m_BitsPerSample/8 * m_Channels.val); //mPeriodBufferLength = m_PeriodSize.val * m_FrameLength ; snd_pcm_hw_params_free(params); return true; }
cst_audiodev *audio_open_alsa(unsigned int sps, int channels) { cst_audiodev *ad; int err; /* alsa specific stuff */ snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *hwparams; snd_pcm_format_t format; /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); /* Open pcm device */ err = snd_pcm_open(&pcm_handle, pcm_dev_name, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { cst_errmsg("audio_open_alsa: failed to open audio device %s. %s\n", pcm_dev_name, snd_strerror(err)); return NULL; } /* Init hwparams with full configuration space */ err = snd_pcm_hw_params_any(pcm_handle, hwparams); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to get hardware parameters from audio device. %s\n", snd_strerror(err)); return NULL; } /* Set access mode */ err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set access mode. %s.\n", snd_strerror(err)); return NULL; } #ifdef WORDS_BIGENDIAN format = SND_PCM_FORMAT_S16_BE; #else format = SND_PCM_FORMAT_S16_LE; #endif /* Set sample format */ err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format); if (err <0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set format. %s.\n", snd_strerror(err)); return NULL; } /* Set sample rate */ err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, sps, 0); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set sample rate near %d. %s.\n", sps, snd_strerror(err)); return NULL; } /* Set number of channels */ assert(channels >0); err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set number of channels to %d. %s.\n", channels, snd_strerror(err)); return NULL; } /* Commit hardware parameters */ err = snd_pcm_hw_params(pcm_handle, hwparams); if (err < 0) { snd_pcm_close(pcm_handle); snd_config_update_free_global(); cst_errmsg("audio_open_alsa: failed to set hw parameters. %s.\n", snd_strerror(err)); return NULL; } /* Make sure the device is ready to accept data */ assert(snd_pcm_state(pcm_handle) == SND_PCM_STATE_PREPARED); /* Write hardware parameters to audio device data structure */ ad = cst_alloc(cst_audiodev, 1); assert(ad != NULL); ad->sps = sps; ad->channels = channels; ad->platform_data = (void *) pcm_handle; return ad; }
static int pcm_open(struct alsa_pcm *alsa, const char *device_name, snd_pcm_stream_t stream, int rate, int buffer_time) { int r, dir; unsigned int p; size_t bytes; snd_pcm_hw_params_t *hw_params; r = snd_pcm_open(&alsa->pcm, device_name, stream, SND_PCM_NONBLOCK); if (!chk("open", r)) return -1; snd_pcm_hw_params_alloca(&hw_params); r = snd_pcm_hw_params_any(alsa->pcm, hw_params); if (!chk("hw_params_any", r)) return -1; r = snd_pcm_hw_params_set_access(alsa->pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (!chk("hw_params_set_access", r)) return -1; r = snd_pcm_hw_params_set_format(alsa->pcm, hw_params, SND_PCM_FORMAT_S16); if (!chk("hw_params_set_format", r)) { fprintf(stderr, "16-bit signed format is not available. " "You may need to use a 'plughw' device.\n"); return -1; } r = snd_pcm_hw_params_set_rate(alsa->pcm, hw_params, rate, 0); if (!chk("hw_params_set_rate", r )) { fprintf(stderr, "%dHz sample rate not available. You may need to use " "a 'plughw' device.\n", rate); return -1; } alsa->rate = rate; r = snd_pcm_hw_params_set_channels(alsa->pcm, hw_params, DEVICE_CHANNELS); if (!chk("hw_params_set_channels", r)) { fprintf(stderr, "%d channel audio not available on this device.\n", DEVICE_CHANNELS); return -1; } p = buffer_time * 1000; /* microseconds */ dir = -1; r = snd_pcm_hw_params_set_buffer_time_near(alsa->pcm, hw_params, &p, &dir); if (!chk("hw_params_set_buffer_time_near", r)) { fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n", buffer_time); return -1; } p = 2; /* double buffering */ dir = 1; r = snd_pcm_hw_params_set_periods_min(alsa->pcm, hw_params, &p, &dir); if (!chk("hw_params_set_periods_min", r)) { fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n", buffer_time); return -1; } r = snd_pcm_hw_params(alsa->pcm, hw_params); if (!chk("hw_params", r)) return -1; r = snd_pcm_hw_params_get_period_size(hw_params, &alsa->period, &dir); if (!chk("get_period_size", r)) return -1; bytes = alsa->period * DEVICE_CHANNELS * sizeof(signed short); alsa->buf = malloc(bytes); if (!alsa->buf) { perror("malloc"); return -1; } /* snd_pcm_readi() returns uninitialised memory on first call, * possibly caused by premature POLLIN. Keep valgrind happy. */ memset(alsa->buf, 0, bytes); return 0; }
/** * This method prepares ALSA system for 22050hz signed 16bits Little Endian * playback. */ void SoundThread::initAlsa() { int err; ostringstream oss; /* Get a handle on the PCM device. */ if ((err = snd_pcm_open (&playback_handle, deviceName, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { oss << "cannot open audio device : " << deviceName << snd_strerror(err) << endl; throw oss.str(); } /* Allocate snd_pcm_hw_params_t structure. */ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { oss << "cannot allocate hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Retrieve current parameters. */ if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { oss << "cannot initialize hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample are NON Interleaved (mono !) */ if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) { oss << "cannot set access type : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample format: Signed 16bit little endian. */ if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { oss << "cannot set sample format : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the Sample rate. */ if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, 22050, 0)) < 0) { oss << "cannot set sample rate : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Channel number (MONO). */ if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0) { oss << "cannot set channel count : " << snd_strerror (err) << endl; throw oss.str(); } if ((err = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, 2048)) < 0) { oss << "cannot set channel buffer size : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply these parameters. */ if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { oss << "cannot apply parameters : " << snd_strerror (err) << endl; throw oss.str(); } snd_pcm_uframes_t bufferSize; snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize ); //cout << "initAlsa: Buffer size = " << bufferSize << " frames." << endl; /* Free memoray allocated for snd_pcm_hw_params_t */ snd_pcm_hw_params_free (hw_params); /* tell ALSA to wake us up whenever 4096 or more frames of playback data can be delivered. Also, tell ALSA that we'll start the device ourselves. */ /* Allocate snd_pcm_sw_params_t structure. */ if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { oss << "cannot allocate software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Get the current software configuration*/ if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) { oss << "cannot initialize software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the wake up point to 2048 (92.9 ms). The minimum data available before asking*/ /* for new ones. */ if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 2048U)) < 0) { oss << "cannot set minimum available count : " << snd_strerror (err) << endl; throw oss.str(); } /* Set when ALSA starts to play. */ if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 1024U)) < 0) { oss << "cannot set start mode : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply parameters. */ if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) { oss << "cannot apply software parameters : " << snd_strerror (err) << endl; throw oss.str(); } /* the interface will interrupt the kernel every 4096 frames, and ALSA will wake up this program very soon after that. */ if ((err = snd_pcm_prepare (playback_handle)) < 0) { oss << "cannot prepare audio interface for use : " << snd_strerror (err) << endl; throw oss.str(); } }
int AlsaAudioPlugin::init(shared_ptr<t_CPC> cpc, shared_ptr<t_PSG> psg) { if(!cpc->snd_enabled) { InfoLogMessage("[ALSA Audio Plugin] Not opening audio because disabled in the config"); return 0; } /* TODO */ unsigned int rate = cpc->snd_playback_rate; int channels = cpc->snd_stereo ? 2 : 1; snd_pcm_format_t format = SND_PCM_FORMAT_S16; switch(cpc->snd_bits) { case 8: format = SND_PCM_FORMAT_U8; break; case 16: format = SND_PCM_FORMAT_S16; break; case 24: format = SND_PCM_FORMAT_S24; break; case 32: format = SND_PCM_FORMAT_S32; break; default: WarningLogMessage("[ALSA Audio Plugin] Warning, %d bits format unknown, fallback to %s.", cpc->snd_bits, snd_pcm_format_name(format)); } int periods = 2; periodsize = 4096; unsigned int exact_rate; int dir, err; /* Handle for the PCM device */ //snd_pcm_t *pcm_handle; /* Playback stream */ snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; /* This structure contains information about */ /* the hardware and can be used to specify the */ /* configuration to be used for the PCM stream. */ snd_pcm_hw_params_t *hwparams; /* Name of the PCM device, like plughw:0,0 */ /* The first number is the number of the soundcard, */ /* the second number is the number of the device. */ char *pcm_name = strdup("plughw:0,0"); WarningLogMessage("TODO [%s:%d]: pcm_name need to be configurable.", __FILE__, __LINE__); /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); /* Open PCM. The last parameter of this function is the mode. */ /* If this is set to 0, the standard mode is used. Possible */ /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */ /* If SND_PCM_NONBLOCK is used, read / write access to the */ /* PCM device will return immediately. If SND_PCM_ASYNC is */ /* specified, SIGIO will be emitted whenever a period has */ /* been completely processed by the soundcard. */ if(err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error opening PCM device %s (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Init hwparams with full configuration space */ if(err = snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Can not configure PCM device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ /* There are also access types for MMAPed */ /* access, but this is beyond the scope */ /* of this introduction. */ if(err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting access on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set sample format */ if(err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting format %s on device %s. (Error: %s)", snd_pcm_format_name(format), pcm_name, snd_strerror(err)); return 1; } /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if 0 // Segfault... Humf... TODO exact_rate = rate; if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &dir) < 0) { ErrorLogMessage("Error setting rate (%d) on device %s.", rate, pcm_name); } if(dir != 0) { WarningLogMessage("The rate %d Hz is not supported by your hardware on device %s.\n" \ "==> Using %d Hz instead.", pcm_name, rate, exact_rate); } #else exact_rate = rate; if(err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, exact_rate, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting rate (%d) on device %s. (Error: %s)", rate, pcm_name, snd_strerror(err)); } #endif /* Set number of channels */ if(err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting channels (%d) on device %s. (Error: %s)", channels, pcm_name, snd_strerror(err)); return 1; } /* Set number of periods. Periods used to be called fragments. */ if(err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting periods (%d) on device %s. (Error: %s)", periods, pcm_name, snd_strerror(err)); return 1; } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ int buffer_size = (periodsize * periods) >> 2; if(err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, buffer_size) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting buffersize (%d) on device %s. (Error: %s)", buffer_size, pcm_name, snd_strerror(err)); return 1; } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if(err = snd_pcm_hw_params(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting HW params on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } sndBuffer = new uint8_t[periodsize*4*2]; if(!sndBuffer) { ErrorLogMessage("[ALSA Audio Plugin] sndBuffer allocation error."); return 1; } sndBufferPtr = sndBuffer; InfoLogMessage("[ALSA Audio Plugin] PCM device %s open at %d Hz %s, %d channels.", pcm_name, rate, snd_pcm_format_name(format), channels); return 0; }
static ALCenum alsa_open_capture(ALCdevice *Device, const ALCchar *deviceName) { const char *driver = NULL; snd_pcm_hw_params_t *hp; snd_pcm_uframes_t bufferSizeInFrames; snd_pcm_uframes_t periodSizeInFrames; ALboolean needring = AL_FALSE; snd_pcm_format_t format; const char *funcerr; alsa_data *data; int err; if(deviceName) { size_t idx; if(!allCaptureDevNameMap) allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); for(idx = 0;idx < numCaptureDevNames;idx++) { if(strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0) { driver = allCaptureDevNameMap[idx].device; break; } } if(idx == numCaptureDevNames) return ALC_INVALID_VALUE; } else { deviceName = alsaDevice; driver = GetConfigValue("alsa", "capture", "default"); } data = (alsa_data*)calloc(1, sizeof(alsa_data)); err = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if(err < 0) { ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(err)); free(data); return ALC_INVALID_VALUE; } format = -1; switch(Device->FmtType) { case DevFmtByte: format = SND_PCM_FORMAT_S8; break; case DevFmtUByte: format = SND_PCM_FORMAT_U8; break; case DevFmtShort: format = SND_PCM_FORMAT_S16; break; case DevFmtUShort: format = SND_PCM_FORMAT_U16; break; case DevFmtInt: format = SND_PCM_FORMAT_S32; break; case DevFmtUInt: format = SND_PCM_FORMAT_U32; break; case DevFmtFloat: format = SND_PCM_FORMAT_FLOAT; break; } funcerr = NULL; bufferSizeInFrames = maxu(Device->UpdateSize*Device->NumUpdates, 100*Device->Frequency/1000); periodSizeInFrames = minu(bufferSizeInFrames, 25*Device->Frequency/1000); snd_pcm_hw_params_malloc(&hp); #define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error CHECK(snd_pcm_hw_params_any(data->pcmHandle, hp)); /* set interleaved access */ CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED)); /* set format (implicitly sets sample bits) */ CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format)); /* set channels (implicitly sets frame bits) */ CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(Device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ CHECK(snd_pcm_hw_params_set_rate(data->pcmHandle, hp, Device->Frequency, 0)); /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ if(snd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, hp, &bufferSizeInFrames) < 0) { TRACE("Buffer too large, using intermediate ring buffer\n"); needring = AL_TRUE; CHECK(snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, hp, &bufferSizeInFrames)); } /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ CHECK(snd_pcm_hw_params_set_period_size_near(data->pcmHandle, hp, &periodSizeInFrames, NULL)); /* install and prepare hardware configuration */ CHECK(snd_pcm_hw_params(data->pcmHandle, hp)); /* retrieve configuration info */ CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL)); #undef CHECK snd_pcm_hw_params_free(hp); hp = NULL; if(needring) { data->ring = CreateRingBuffer(FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType), Device->UpdateSize*Device->NumUpdates); if(!data->ring) { ERR("ring buffer create failed\n"); goto error2; } data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames); data->buffer = malloc(data->size); if(!data->buffer) { ERR("buffer malloc failed\n"); goto error2; } } Device->DeviceName = strdup(deviceName); Device->ExtraData = data; return ALC_NO_ERROR; error: ERR("%s failed: %s\n", funcerr, snd_strerror(err)); if(hp) snd_pcm_hw_params_free(hp); error2: free(data->buffer); DestroyRingBuffer(data->ring); snd_pcm_close(data->pcmHandle); free(data); Device->ExtraData = NULL; return ALC_INVALID_VALUE; }
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); }
int set_hwparams(snd_pcm_t *handle, int sampleRate, int channels, int bufferSize) { snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED; int ret, dir; snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams); /* choose all parameters */ ret = snd_pcm_hw_params_any(handle, hwparams); if (ret < 0) { fprintf(stderr, "Broken configuration for playback: " "no configurations available: %s\n", snd_strerror(ret)); return ret; } /* set hardware resampling */ ret = snd_pcm_hw_params_set_rate_resample(handle, hwparams, resample); if (ret < 0) { fprintf(stderr, "Resampling setup failed for playback: %s\n", snd_strerror(ret)); return ret; } /* set the interleaved read/write format */ ret = snd_pcm_hw_params_set_access(handle, hwparams, access); if (ret < 0) { fprintf(stderr, "Access type not available for playback: %s\n", snd_strerror(ret)); return ret; } /* set the sample format */ ret = snd_pcm_hw_params_set_format(handle, hwparams, format); if (ret < 0) { fprintf(stderr, "Sample format not available for playback: %s\n", snd_strerror(ret)); return ret; } /* set the count of channels */ ret = snd_pcm_hw_params_set_channels(handle, hwparams, channels); if (ret < 0) { fprintf(stderr, "Channels count (%d) not available for playbacks: %s\n", channels, snd_strerror(ret)); return ret; } /* set the stream rate */ int rate = sampleRate; ret = snd_pcm_hw_params_set_rate(handle, hwparams, rate, 0); if (ret < 0) { fprintf(stderr, "Rate %dHz not available for playback: %s\n", sampleRate, snd_strerror(ret)); return ret; } if (rate != sampleRate) { fprintf(stderr, "Rate doesn't match (requested %dHz, get %dHz)\n", rate, ret); return -EINVAL; } /* set the buffer frames */ unsigned int buffer_frames = bufferSize / 2 / channels; // bytes to frames ret = snd_pcm_hw_params_set_buffer_size(handle, hwparams, buffer_frames); if (ret < 0) { fprintf(stderr, "Unable to set buffer size %d for playback: %s\n", buffer_frames, snd_strerror(ret)); return ret; } /* set the period time */ dir = 0; ret = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if (ret < 0) { fprintf(stderr, "Unable to set period time %d for playback: %s\n", period_time, snd_strerror(ret)); return ret; } /* write the parameters to device */ ret = snd_pcm_hw_params(handle, hwparams); if (ret < 0) { fprintf(stderr, "Unable to set hw params for playback: %s\n", snd_strerror(ret)); return ret; } dump_hwparams(handle); }
FFTWidget::FFTWidget(QWidget *parent) : QWidget(parent) { int err; snd_pcm_hw_params_t *hw_params; const char *dev_name = "hw:SDR"; if ((err = snd_pcm_open(&capture_handle, dev_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev_name, snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, 96000, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare (capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } setRectWindow(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(processFFT())); timer->start(); // Zero-delay if((err = snd_pcm_start(capture_handle)) < 0) { fprintf (stderr, "cannot start audio interface (%s)\n", snd_strerror (err)); exit(1); } }
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; // open() if(!dev.contains(QLatin1String("default"))) { int idx = snd_card_get_index(dev.toLocal8Bit().constData()); dev = QString(QLatin1String("hw:%1,0")).arg(idx); } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); } else { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); } if(err < 0) { handle = 0; return false; } bool testChannel = false; bool testCodec = false; bool testFreq = false; bool testType = false; bool testSize = false; int dir = 0; snd_pcm_nonblock( handle, 0 ); snd_pcm_hw_params_alloca( ¶ms ); snd_pcm_hw_params_any( handle, params ); // set the values! snd_pcm_hw_params_set_channels(handle,params,format.channels()); snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) 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) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) 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) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) 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; }
/*---------------------------------------------------------------- TIesrFA_ALSA_open Try to open an ALSA audio PCM channel. ----------------------------------------------------------------*/ TIesrFA_ALSA_Error_t TIesrFA_ALSA_open( TIesrFA_t * const aTIesrFAInstance ) { int rtnStatus; int openSuccess = 0; snd_pcm_uframes_t numSamples; snd_pcm_hw_params_t *hw_params = 0; snd_pcm_sw_params_t *sw_params = 0; TIesrFA_ALSA_t * const ALSAData = (TIesrFA_ALSA_t * const) aTIesrFAInstance->impl_data; /* Try to open a handle to the ALSA pcm in blocking mode. */ rtnStatus = snd_pcm_open( &ALSAData->alsa_handle, aTIesrFAInstance->channel_name, SND_PCM_STREAM_CAPTURE, 0 ); if( rtnStatus < 0 ) goto openExit; /* Set up the information for recording from the audio channelport. This will include data specified by the user, such as data in aTIesrFAInstance->encoding, etc. If setup fails, then the audio channel should be shut down and failure reported. */ /* Setup hardware parameters of the ALSA pcm */ rtnStatus = snd_pcm_hw_params_malloc( &hw_params ); if( rtnStatus < 0 ) goto openExit; rtnStatus = snd_pcm_hw_params_any( ALSAData->alsa_handle, hw_params ); if( rtnStatus < 0 ) goto openExit; /* There will only be a single channel */ rtnStatus = snd_pcm_hw_params_set_channels( ALSAData->alsa_handle, hw_params, 1 ); if( rtnStatus < 0 ) goto openExit; /* Even though only one channel, must specify type of read. */ rtnStatus = snd_pcm_hw_params_set_access( ALSAData->alsa_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); if( rtnStatus < 0 ) goto openExit; /* Format type - only 16 bit linear for now */ rtnStatus = snd_pcm_hw_params_set_format( ALSAData->alsa_handle, hw_params, SND_PCM_FORMAT_S16 ); if( rtnStatus < 0 ) goto openExit; /* Set sample rate, it must be exactly supported */ rtnStatus = snd_pcm_hw_params_set_rate( ALSAData->alsa_handle, hw_params, aTIesrFAInstance->sample_rate, 0 ); if( rtnStatus < 0 ) goto openExit; /* Size of ALSA PCM ring buffer is set to approximately the desired number of multiples of read_samples in the buffer */ numSamples = aTIesrFAInstance->num_audio_buffer_frames * ALSAData->read_samples; rtnStatus = snd_pcm_hw_params_set_buffer_size_near( ALSAData->alsa_handle, hw_params, &numSamples ); if( rtnStatus < 0 ) goto openExit; /* Set the hardware parameters in the PCM*/ rtnStatus = snd_pcm_hw_params( ALSAData->alsa_handle, hw_params ); if( rtnStatus < 0 ) goto openExit; /* Set software parameters to interrupt at the end of an audio buffer number of samples and to start-up manually */ rtnStatus = snd_pcm_sw_params_malloc( &sw_params ); if( rtnStatus < 0 ) goto openExit; rtnStatus = snd_pcm_sw_params_current( ALSAData->alsa_handle, sw_params ); if( rtnStatus < 0 ) goto openExit; /* Number of samples needed in PCM buffer prior to interrupt */ rtnStatus = snd_pcm_sw_params_set_avail_min( ALSAData->alsa_handle, sw_params, ALSAData->read_samples ); if( rtnStatus < 0 ) goto openExit; /* Set start threshold so startup is done manually */ rtnStatus = snd_pcm_sw_params_set_start_threshold( ALSAData->alsa_handle, sw_params, ULONG_MAX ); if( rtnStatus < 0 ) goto openExit; /* Channel opened successfully */ openSuccess = 1; openExit: if( hw_params != NULL ) snd_pcm_hw_params_free( hw_params ); if( sw_params != NULL ) snd_pcm_sw_params_free( sw_params ); if( openSuccess ) return TIesrFA_ALSAErrNone; return TIesrFA_ALSAErrFail; }
static snd_pcm_t *alsa_open(char *dev, int rate, int channels) { snd_pcm_hw_params_t *hwp; snd_pcm_sw_params_t *swp; snd_pcm_t *h; int r; int dir; snd_pcm_uframes_t period_size_min; snd_pcm_uframes_t period_size_max; snd_pcm_uframes_t buffer_size_min; snd_pcm_uframes_t buffer_size_max; snd_pcm_uframes_t period_size; snd_pcm_uframes_t buffer_size; if ((r = snd_pcm_open(&h, dev, SND_PCM_STREAM_PLAYBACK, 0) < 0)) return NULL; hwp = alloca(snd_pcm_hw_params_sizeof()); memset(hwp, 0, snd_pcm_hw_params_sizeof()); snd_pcm_hw_params_any(h, hwp); snd_pcm_hw_params_set_access(h, hwp, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(h, hwp, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate(h, hwp, rate, 0); snd_pcm_hw_params_set_channels(h, hwp, channels); /* Configurue period */ dir = 0; snd_pcm_hw_params_get_period_size_min(hwp, &period_size_min, &dir); dir = 0; snd_pcm_hw_params_get_period_size_max(hwp, &period_size_max, &dir); period_size = 1024; dir = 0; r = snd_pcm_hw_params_set_period_size_near(h, hwp, &period_size, &dir); if (r < 0) { fprintf(stderr, "audio: Unable to set period size %lu (%s)\n", period_size, snd_strerror(r)); snd_pcm_close(h); return NULL; } dir = 0; r = snd_pcm_hw_params_get_period_size(hwp, &period_size, &dir); if (r < 0) { fprintf(stderr, "audio: Unable to get period size (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } /* Configurue buffer size */ snd_pcm_hw_params_get_buffer_size_min(hwp, &buffer_size_min); snd_pcm_hw_params_get_buffer_size_max(hwp, &buffer_size_max); buffer_size = period_size * 4; dir = 0; r = snd_pcm_hw_params_set_buffer_size_near(h, hwp, &buffer_size); if (r < 0) { fprintf(stderr, "audio: Unable to set buffer size %lu (%s)\n", buffer_size, snd_strerror(r)); snd_pcm_close(h); return NULL; } r = snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size); if (r < 0) { fprintf(stderr, "audio: Unable to get buffer size (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } /* write the hw params */ r = snd_pcm_hw_params(h, hwp); if (r < 0) { fprintf(stderr, "audio: Unable to configure hardware parameters (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } /* * Software parameters */ swp = alloca(snd_pcm_sw_params_sizeof()); memset(hwp, 0, snd_pcm_sw_params_sizeof()); snd_pcm_sw_params_current(h, swp); r = snd_pcm_sw_params_set_avail_min(h, swp, period_size); if (r < 0) { fprintf(stderr, "audio: Unable to configure wakeup threshold (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } snd_pcm_sw_params_set_start_threshold(h, swp, 0); if (r < 0) { fprintf(stderr, "audio: Unable to configure start threshold (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } r = snd_pcm_sw_params(h, swp); if (r < 0) { fprintf(stderr, "audio: Cannot set soft parameters (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } r = snd_pcm_prepare(h); if (r < 0) { fprintf(stderr, "audio: Cannot prepare audio for playback (%s)\n", snd_strerror(r)); snd_pcm_close(h); return NULL; } return h; }
static bool audio_capture_configure(uint32_t samplerate) { assert(acapt_hdl != NULL); snd_pcm_hw_params_t *hw_params = NULL; snd_pcm_hw_params_alloca(&hw_params); int err = 0; /* set hardware params */ if ((err = snd_pcm_hw_params_any(acapt_hdl, hw_params)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params_any() has failed - %s\n", snd_strerror(err)); return false; } /* interleaved samples */ if ((err = snd_pcm_hw_params_set_access(acapt_hdl, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params_set_access() has " "failed - %s\n", snd_strerror(err)); return false; } /* 1 channel (mono) capture */ if ((err = snd_pcm_hw_params_set_channels(acapt_hdl, hw_params, 1)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params_set_channels() has " "failed - %s\n", snd_strerror(err)); return false; } /* 16 bit PCM samples */ if ((err = snd_pcm_hw_params_set_format(acapt_hdl, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params_set_format() has " "failed - %s\n", snd_strerror(err)); return false; } /* set samplerate */ if ((err = snd_pcm_hw_params_set_rate(acapt_hdl, hw_params, samplerate, 0)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params_set_rate() has " "failed - %s\n", snd_strerror(err)); return false; } /* apply hardware parameters */ if ((err = snd_pcm_hw_params(acapt_hdl, hw_params)) < 0) { fprintf(stderr, "ERROR: snd_pcm_hw_params() has failed - %s\n\n", snd_strerror(err)); return false; } /* set software parameters */ snd_pcm_sw_params_t *sw_params = NULL; snd_pcm_sw_params_alloca(&sw_params); if ((err = snd_pcm_sw_params_current(acapt_hdl, sw_params)) < 0) { fprintf(stderr, "ERROR: snd_pcm_sw_params_current() has failed - %s\n", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_set_start_threshold(acapt_hdl, sw_params, 0U)) < 0) { fprintf(stderr, "ERROR: snd_pcm_sw_params_set_start_threshold() has " "failed - %s\n", snd_strerror(err)); return false; } /* apply software parameters */ if ((err = snd_pcm_sw_params(acapt_hdl, sw_params)) < 0) { fprintf(stderr, "ERROR: snd_pcm_sw_params() has failed - %s\n", snd_strerror(err)); return false; } return true; }
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; }
static int pcm_open(pcm_handle_t* pcm, const pcm_desc_t* desc) { const snd_pcm_format_t fmt = SND_PCM_FORMAT_S16_LE; snd_pcm_stream_t stm; int err; if (desc->flags & PCM_FLAG_IN) stm = SND_PCM_STREAM_CAPTURE; else stm = SND_PCM_STREAM_PLAYBACK; err = snd_pcm_open (&pcm->pcm, desc->name, stm, SND_PCM_NONBLOCK); if (err) PERROR_GOTO(snd_strerror(err), on_error_0); err = snd_pcm_hw_params_malloc(&pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_1); err = snd_pcm_hw_params_any(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_access (pcm->pcm, pcm->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_format(pcm->pcm, pcm->hw_params, fmt); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_rate (pcm->pcm, pcm->hw_params, desc->fsampl, 0); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); pcm->nchan = desc->nchan; pcm->wchan = (size_t)snd_pcm_format_physical_width(fmt) / 8; pcm->scale = pcm->nchan * pcm->wchan; err = snd_pcm_hw_params_set_channels (pcm->pcm, pcm->hw_params, desc->nchan); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_malloc(&pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_current(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #if 1 err = snd_pcm_sw_params_set_avail_min (pcm->pcm, pcm->sw_params, 1024); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif #if 1 err = snd_pcm_sw_params_set_start_threshold (pcm->pcm, pcm->sw_params, 0U); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif err = snd_pcm_sw_params(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); err = snd_pcm_prepare(pcm->pcm); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); pcm->rpos = 0; pcm->wpos = 0; pcm->nsampl = (size_t)desc->fsampl * 10; pcm->buf = malloc(pcm->nsampl * pcm->scale); if (pcm->buf == NULL) goto on_error_3; return 0; on_error_3: snd_pcm_sw_params_free(pcm->sw_params); on_error_2: snd_pcm_hw_params_free(pcm->hw_params); on_error_1: snd_pcm_close(pcm->pcm); on_error_0: return -1; }
static int capture(lua_State *lstate) { char *card; snd_pcm_sw_params_t *sparams; int ret, dir, i; snd_pcm_format_t f, format; unsigned int rate, buffer_time; if (rbuf == NULL) { rbuf = new_ringbuf(jack_sr, CHANNELS, BUFSECS, 0.333, 0.667); } getstring(lstate, "card", &card); lua_pop(lstate, 1); for (i = 0; i < 20; i++) { ret = snd_pcm_open(&handle, card, SND_PCM_STREAM_CAPTURE, 0); if (ret < 0) { logmsg("can't open %s (%s)\n", card, snd_strerror(ret)); } else { break; } } free(card); if (ret < 0) return 0; if (hparams != NULL) snd_pcm_hw_params_free(hparams); snd_pcm_hw_params_malloc(&hparams); snd_pcm_hw_params_any(handle, hparams); for (f = format = 0; f < SND_PCM_FORMAT_LAST; f++) { ret = snd_pcm_hw_params_test_format(handle, hparams, f); if (ret == 0) { logmsg("- %s\n", snd_pcm_format_name(f)); format = f; } } ret = snd_pcm_hw_params_set_access(handle, hparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (ret < 0) { logmsg("access %s\n", snd_strerror(ret)); } ret = snd_pcm_hw_params_set_format(handle, hparams, format); logmsg("format: %s\n", snd_pcm_format_description(format)); if (ret < 0) { logmsg("format error %s\n", snd_strerror(ret)); } snd_pcm_hw_params_get_buffer_time_max(hparams, &buffer_time, 0); rate = jack_sr; ret = snd_pcm_hw_params_set_rate(handle, hparams, rate, 0); logmsg("rate %d\n", rate); if (ret < 0) logmsg("rate error %s\n", snd_strerror(ret)); snd_pcm_hw_params_set_channels(handle, hparams, CHANNELS); blocksize = BLOCKSIZE; snd_pcm_hw_params_set_period_size(handle, hparams, blocksize, 0); logmsg("period %ld\n", blocksize); snd_pcm_hw_params_set_buffer_time_near(handle, hparams, &buffer_time, &dir); logmsg("buffer time %u\n", buffer_time); if ((ret = snd_pcm_hw_params(handle, hparams)) < 0) { logmsg("can't set hardware: %s\n", snd_strerror(ret)); return 0; } else logmsg("hardware configd\n"); snd_pcm_sw_params_malloc(&sparams); snd_pcm_sw_params_current(handle, sparams); snd_pcm_sw_params_set_avail_min(handle, sparams, blocksize); snd_pcm_sw_params_set_start_threshold(handle, sparams, 0U); if ((ret = snd_pcm_sw_params(handle, sparams)) < 0) { logmsg("can't set software: %s\n", snd_strerror(ret)); } else logmsg("software configd\n"); snd_pcm_sw_params_free(sparams); pthread_create(&thread_id, NULL, dev_thread, NULL); return 0; }
bool QAlsaAudioDeviceInfo::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 = -1; snd_pcm_t* pcmHandle; snd_pcm_hw_params_t *params; QString dev; #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = device; if (dev.compare(QLatin1String("default")) == 0) { QList<QByteArray> devices = availableDevices(QAudio::AudioOutput); if (!devices.isEmpty()) dev = QLatin1String(devices.first().constData()); } #else if (dev.compare(QLatin1String("default")) == 0) { dev = QLatin1String("hw:0,0"); } 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 snd_pcm_stream_t stream = mode == QAudio::AudioOutput ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE; if (snd_pcm_open(&pcmHandle, dev.toLocal8Bit().constData(), stream, 0) < 0) return false; snd_pcm_nonblock(pcmHandle, 0); snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(pcmHandle, params); // set the values! snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount()); snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0); snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_UNKNOWN; switch (format.sampleSize()) { case 8: if (format.sampleType() == QAudioFormat::SignedInt) pcmFormat = SND_PCM_FORMAT_S8; else if (format.sampleType() == QAudioFormat::UnSignedInt) pcmFormat = SND_PCM_FORMAT_U8; break; case 16: if (format.sampleType() == QAudioFormat::SignedInt) { pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE; } else if (format.sampleType() == QAudioFormat::UnSignedInt) { pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian ? SND_PCM_FORMAT_U16_LE : SND_PCM_FORMAT_U16_BE; } break; case 32: if (format.sampleType() == QAudioFormat::SignedInt) { pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian ? SND_PCM_FORMAT_S32_LE : SND_PCM_FORMAT_S32_BE; } else if (format.sampleType() == QAudioFormat::UnSignedInt) { pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian ? SND_PCM_FORMAT_U32_LE : SND_PCM_FORMAT_U32_BE; } else if (format.sampleType() == QAudioFormat::Float) { pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian ? SND_PCM_FORMAT_FLOAT_LE : SND_PCM_FORMAT_FLOAT_BE; } } if (pcmFormat != SND_PCM_FORMAT_UNKNOWN) err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat); // For now, just accept only audio/pcm codec if (!format.codec().startsWith(QLatin1String("audio/pcm"))) err = -1; if (err >= 0 && format.channelCount() != -1) { err = snd_pcm_hw_params_test_channels(pcmHandle, params, format.channelCount()); if (err >= 0) err = snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount()); } if (err >= 0 && format.sampleRate() != -1) { err = snd_pcm_hw_params_test_rate(pcmHandle, params, format.sampleRate(), 0); if (err >= 0) err = snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0); } if (err >= 0 && pcmFormat != SND_PCM_FORMAT_UNKNOWN) err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat); if (err >= 0) err = snd_pcm_hw_params(pcmHandle, params); snd_pcm_close(pcmHandle); return (err == 0); }