int setparams_bufsize(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *tparams, snd_pcm_uframes_t bufsize, const char *id) { int err; snd_pcm_uframes_t periodsize; snd_pcm_hw_params_copy(params, tparams); periodsize = bufsize * 2; err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize); if (err < 0) { printf("Unable to set buffer size %li for %s: %s\n", bufsize * 2, id, snd_strerror(err)); return err; } if (period_size > 0) periodsize = period_size; else periodsize /= 2; err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0); if (err < 0) { printf("Unable to set period size %li for %s: %s\n", periodsize, id, snd_strerror(err)); return err; } return 0; }
//open a sound device with specified period, rate, channels(0=mono,1=stereo or MONO_SOUND/STEREO_SOUND) // and direction(0=playback,1=capture), returns the buffer (also PLAYBACK_DIR/CAPTURE_DIR) snd_pcm_t* start_snd_device(size_t period, unsigned int rate, int stereo, int direction){ //Open PCM device for playback/capture, check for errors snd_pcm_t *pcm_handle; //handler struct int dir = (direction)? SND_PCM_STREAM_CAPTURE:SND_PCM_STREAM_PLAYBACK; int rc = snd_pcm_open(&pcm_handle, "default",dir, 0); if (rc < 0){ //make sure it landed fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc)); return 0; //return null pointer } //Setup the hardware parameters snd_pcm_hw_params_t *params; //create pointer snd_pcm_hw_params_alloca(¶ms); //allocate struct snd_pcm_hw_params_any(pcm_handle, params); //fill with defaults snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //interleaved mode snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); //signed 16-bit LE snd_pcm_hw_params_set_channels(pcm_handle, params, (stereo+1)); //stereo mode unsigned int rate2 = rate; //copy rate (will be overwritten on mismatch) int err_dir = 0; //try to set rate exactly snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate2, &err_dir); //get closest match if(rate != rate2) printf("Rate mismatch, %d give, %d set\n",rate,rate2); size_t frames = period; //once again,copy value in case of mismatch snd_pcm_hw_params_set_period_size_near(pcm_handle, params, &period, &dir); //set the period if(period != frames) printf("Period size mismatch, %d given, %d set", (int)period, (int)frames); //Write the parameters to the driver rc = snd_pcm_hw_params(pcm_handle, params); if (rc < 0){ //make sure it landed fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); return 0; //return null } return pcm_handle; }
static void audio_renderer_init() { int rc; decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc); snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_uframes_t period_size = FRAME_SIZE * CHANNEL_COUNT * 2; snd_pcm_uframes_t buffer_size = 12 * period_size; unsigned int sampleRate = SAMPLE_RATE; /* Open PCM device for playback. */ CHECK_RETURN(snd_pcm_open(&handle, audio_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) /* Set hardware parameters */ CHECK_RETURN(snd_pcm_hw_params_malloc(&hw_params)); CHECK_RETURN(snd_pcm_hw_params_any(handle, hw_params)); CHECK_RETURN(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)); CHECK_RETURN(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE)); CHECK_RETURN(snd_pcm_hw_params_set_rate_near(handle, hw_params, &sampleRate, NULL)); CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, CHANNEL_COUNT)); CHECK_RETURN(snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size)); CHECK_RETURN(snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL)); CHECK_RETURN(snd_pcm_hw_params(handle, hw_params)); snd_pcm_hw_params_free(hw_params); /* Set software parameters */ CHECK_RETURN(snd_pcm_sw_params_malloc(&sw_params)); CHECK_RETURN(snd_pcm_sw_params_current(handle, sw_params)); CHECK_RETURN(snd_pcm_sw_params_set_start_threshold(handle, sw_params, buffer_size - period_size)); CHECK_RETURN(snd_pcm_sw_params_set_avail_min(handle, sw_params, period_size)); CHECK_RETURN(snd_pcm_sw_params(handle, sw_params)); snd_pcm_sw_params_free(sw_params); CHECK_RETURN(snd_pcm_prepare(handle)); }
int nv_alsa_init(unsigned int channelCount, unsigned int sampleRate, unsigned char* device) { int rc; snd_pcm_hw_params_t *params; int dir; /* Open PCM device for playback. */ if ((rc = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) != 0) return rc; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); if ((rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) != 0) return rc; if ((rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) != 0) return rc; if ((rc = snd_pcm_hw_params_set_channels(handle, params, channelCount)) != 0) return rc; if ((rc = snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, &dir)) != 0) return rc; snd_pcm_uframes_t frames = 32; if ((rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir)) != 0) return rc; if ((rc = snd_pcm_hw_params(handle, params)) != 0) return rc; }
// Set device parameters. MapilVoid ALSASoundDevice::SetParam( PCMDevConf* pConf ) { _snd_pcm_format pcmFmt[] = { SND_PCM_FORMAT_UNKNOWN, SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE }; // Allocate hardware parameter. snd_pcm_hw_params_alloca( &m_pParam ); // Get default hardware parameter. snd_pcm_hw_params_any( m_pHandle, m_pParam ); // Set parameters. snd_pcm_hw_params_set_access( m_pHandle, m_pParam, SND_PCM_ACCESS_RW_INTERLEAVED ); snd_pcm_hw_params_set_format( m_pHandle, m_pParam, pcmFmt[ pConf->m_Fmt ] ); snd_pcm_hw_params_set_channels( m_pHandle, m_pParam, pConf->m_Channel ); MapilInt32 val; snd_pcm_hw_params_set_rate_near( m_pHandle, m_pParam, &pConf->m_Freq, &val ); snd_pcm_uframes_t frame = 32; snd_pcm_hw_params_set_period_size_near( m_pHandle, m_pParam, &frame, &val ); if( snd_pcm_hw_params( m_pHandle, m_pParam ) < 0 ){ exit( 1 ); } }
void* audio_init(int sampling_rate) { syslog(LOG_INFO, "ALSA: audio_set_driver: this sets the PCM device to :%s\n",g_card); #ifdef DEBUGALSA syslog(LOG_DEBUG,"ALSA: Sample rate proposed %d\n",sampling_rate); #endif int rc, dir = 0; snd_pcm_uframes_t frames = 32; // rc = snd_pcm_open(&alsa_handle, g_card, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); rc = snd_pcm_open(&alsa_handle, g_card, SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { syslog(LOG_ERR, "unable to open pcm device: %s\n", snd_strerror(rc)); die("alsa initialization failed"); } snd_pcm_hw_params_alloca(&alsa_params); snd_pcm_hw_params_any(alsa_handle, alsa_params); snd_pcm_hw_params_set_access(alsa_handle, alsa_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa_handle, alsa_params, SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, NUM_CHANNELS); snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, (unsigned int *)&sampling_rate, &dir); #ifdef DEBUGALSA syslog(LOG_DEBUG,"ALSA: Sample rate gotten %d\n",sampling_rate); #endif snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &frames, &dir); rc = snd_pcm_hw_params(alsa_handle, alsa_params); if (rc < 0) { syslog(LOG_ERR, "unable to set hw parameters: %s\n", snd_strerror(rc)); die("alsa initialization failed"); } return alsa_handle; }
void audio_init(void) { int ret, dir; unsigned int rate; snd_pcm_hw_params_t * params; rate = 44100; frames = 32; ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) { fprintf(stderr, "Unable to open pcm device: %s\n", snd_strerror(ret)); exit(EXIT_FAILURE); } snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 2); snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); ret = snd_pcm_hw_params(handle, params); if (ret < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(ret)); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_period_size(params, &frames, &dir); }
static void alsa_set_hw_params(struct alsa_dev *dev, snd_pcm_t *handle, unsigned int rate, int channels, int period) { int dir, ret; snd_pcm_uframes_t period_size; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hw_params; ret = snd_pcm_hw_params_malloc(&hw_params); if (ret < 0) syslog_panic("Cannot allocate hardware parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_any(handle, hw_params); if (ret < 0) syslog_panic("Cannot initialize hardware parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (ret < 0) syslog_panic("Cannot set access type: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE); if (ret < 0) syslog_panic("Cannot set sample format: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0); if (ret < 0) syslog_panic("Cannot set sample rate: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_channels(handle, hw_params, channels); if (ret < 0) syslog_panic("Cannot set channel number: %s\n", snd_strerror(ret)); period_size = period; dir = 0; ret = snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, &dir); if (ret < 0) syslog_panic("Cannot set period size: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_periods(handle, hw_params, PERIODS, 0); if (ret < 0) syslog_panic("Cannot set period number: %s\n", snd_strerror(ret)); buffer_size = period_size * PERIODS; dir = 0; ret = snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size); if (ret < 0) syslog_panic("Cannot set buffer size: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params(handle, hw_params); if (ret < 0) syslog_panic("Cannot set capture parameters: %s\n", snd_strerror(ret)); snd_pcm_hw_params_free(hw_params); }
bool SoundProcessor::SetUpRecorder(){ rc_m = snd_pcm_open(&handle_m, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc_m < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc_m)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms_m); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle_m, params_m); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle_m, params_m, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle_m, params_m, SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle_m, params_m, 1); /* 44100 bits/second sampling rate (CD quality) */ val_m = 8000; snd_pcm_hw_params_set_rate_near(handle_m, params_m, &val_m, &dir_m); /* Set period size to 32 frames. */ //frames = 32; snd_pcm_hw_params_set_period_size_near(handle_m, params_m, &frames, &dir_m); /* Write the parameters to the driver */ rc_m = snd_pcm_hw_params(handle_m, params_m); if (rc_m < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc_m)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params_m, &frames, &dir_m); size = frames; /* 2 bytes/sample, 2 channels */ buffer_m = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params_m, &val_m, &dir_m); return true; }
void Recorder::initRecoder() { int rc; snd_pcm_hw_params_t *params; unsigned int val; int dir=0; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default",SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, CHANNELS); /* 44100 bits/second sampling rate (CD quality) */ val = SAMPLERATE; 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 * 2; /* 2 bytes/sample, 2 channels */ /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params,&val, &dir); //loops = 5000000 / val; //获取5秒中所对应的loop这里用不到 }
int audio_capture_init(char *audio_dev) { unsigned int val; int dir, rc, size; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); return -1; } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&hw_params); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, hw_params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE); /* 1 channel mono */ snd_pcm_hw_params_set_channels(handle, hw_params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, hw_params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, hw_params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, hw_params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); return -1; } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ frame_buffer = (char *) malloc(size); printf("- Allocated %d bytes frame buffer\n", size); snd_pcm_hw_params_get_period_time(hw_params, &val, &dir); return 0; }
void set_hwparams(snd_pcm_t *phandle) { int err; snd_pcm_hw_params_t *params; err = snd_output_stdio_attach(&log, stderr, 0); if (err < 0) { fprintf(stderr, "cannot attach output stdio\n"); exit(0); } snd_pcm_hw_params_alloca(¶ms); err = snd_pcm_hw_params_any(phandle, params); if (err < 0) { fprintf(stderr, "Broken configuration for this PCM: no configurations available\n"); exit(0); } err = snd_pcm_hw_params_set_access(phandle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { fprintf(stderr, "Access type not available\n"); exit(0); } err = snd_pcm_hw_params_set_format(phandle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { fprintf(stderr, "cannot set format\n"); exit(0); } err = snd_pcm_hw_params_set_channels(phandle, params, 2); if (err < 0) { fprintf(stderr, "cannot set channels 2\n"); exit(0); } err = snd_pcm_hw_params_set_rate_near(phandle, params, 44100, 0); if (err < 0) { fprintf(stderr, "cannot set rate\n"); exit(0); } err = snd_pcm_hw_params_set_period_size_near(phandle, params, period_size); if (err < 0) { fprintf(stderr, "cannot set period size\n"); exit(0); } err = snd_pcm_hw_params(phandle, params); if (err < 0) { fprintf(stderr, "Unable to install hw params:\n"); exit(0); } snd_pcm_hw_params_dump(params, log); }
/**************************************************************************************** * 函数名: init_alsa_play * 输 入: 无 * 输 出: 无 * 功能说明:alsa音频播放器初始化 * * ******************************************************************************************/ void init_alsa_play() { snd_pcm_hw_params_t *params; unsigned int val; int dir; /* Open PCM device for playback. */ rc=snd_pcm_open(&handle,"plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0); if (rc< 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle,params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format 格式*/ snd_pcm_hw_params_set_format(handle,params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) 声道*/ snd_pcm_hw_params_set_channels(handle, params, channels); /* 32000 bits/second sampling rate (CD quality) 采样率设置*/ snd_pcm_hw_params_set_rate_near(handle,params, &rate, &dir); /* Set period size to 32 frames. */ frames = SAMPLERATE/1000*READMSFORONCE; 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); //32个采样点算一帧 size = frames * (channels); /* 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); }
void carmen_sound_set_device_parameters(snd_pcm_t *handle, int sampling_rate, int num_frames) { int rc, dir; unsigned int val; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames; val = sampling_rate; frames = (snd_pcm_uframes_t) num_frames; /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* 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); /* set bits/second sampling rate */ snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to num of frames. */ 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) exit(printf("unable to set hw parameters: %s\n", snd_strerror(rc))); /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); // @TODO: pesquisar por que tem que ler um pouco que vem vazio nao sei por que... char buffer[4 * 32]; rc = snd_pcm_readi(handle, buffer, 32); }
void AudioWalkera::setupAlsa(){ int dir; int t = 0, i, c; rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if(rc < 0) exitError("Could not open pcm device"); snd_pcm_hw_params_alloca(¶ms); //rc = setupHardware(handle, params, &dir); snd_pcm_uframes_t frames_inner; unsigned int val; 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_LE); snd_pcm_hw_params_set_channels(handle, params, 1); val = 48000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); frames_inner = 2304; snd_pcm_hw_params_set_period_size_near(handle, params, &frames_inner, &dir); rc = snd_pcm_hw_params(handle, params); if(rc < 0) exitError("Could not set hardware parameters"); snd_pcm_hw_params_get_period_size(params, &frames, &dir); buffer = (short*) calloc(frames, sizeof(short)); }
int sound_init () { int rc; 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)); return rc; } g_paused = 0; snd_pcm_hw_params_alloca (¶ms); snd_pcm_hw_params_any (handle, params); snd_pcm_hw_params_set_access (handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format (handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels (handle, params, CHANNELS); val = RATE; snd_pcm_hw_params_set_rate_near (handle, params, &val, &dir); frames = FRAMES; snd_pcm_hw_params_set_period_size_near (handle, params, &frames, &dir); rc = snd_pcm_hw_params (handle, params); if (rc < 0) return rc; snd_pcm_hw_params_get_period_size (params, &frames, &dir); snd_pcm_hw_params_get_period_time (params, &val, &dir); return 0; }
static void start(int sample_rate) { if (sample_rate != 44100) die("Unexpected sample rate!"); int ret, dir = 0; snd_pcm_uframes_t frames = 64; ret = snd_pcm_open(&alsa_handle, alsa_out_dev, SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) die("Alsa initialization failed: unable to open pcm device: %s\n", snd_strerror(ret)); snd_pcm_hw_params_alloca(&alsa_params); snd_pcm_hw_params_any(alsa_handle, alsa_params); snd_pcm_hw_params_set_access(alsa_handle, alsa_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa_handle, alsa_params, SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2); snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, (unsigned int *)&sample_rate, &dir); snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &frames, &dir); ret = snd_pcm_hw_params(alsa_handle, alsa_params); if (ret < 0) die("unable to set hw parameters: %s\n", snd_strerror(ret)); }
SoundOutput_alsa::SoundOutput_alsa(int mixing_frequency, int mixing_latency) : SoundOutput_Impl(mixing_frequency, mixing_latency), frames_in_buffer(4096), frames_in_period(1024) { int rc; snd_pcm_hw_params_t *hwparams; rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { log_event("warn", "ClanSound: Couldn't open sound device, disabling sound"); handle = nullptr; return; } snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_any(handle, hwparams); snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_FLOAT); snd_pcm_hw_params_set_channels(handle, hwparams, 2); snd_pcm_hw_params_set_rate_near(handle, hwparams, (unsigned int *)&this->mixing_frequency, nullptr); snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &frames_in_buffer); frames_in_period = frames_in_buffer / 4; snd_pcm_hw_params_set_period_size_near(handle, hwparams, &frames_in_period, nullptr); rc = snd_pcm_hw_params(handle, hwparams); if (rc < 0) { log_event("warn", "ClanSound: Couldn't initialize sound device, disabling sound"); snd_pcm_close(handle); handle = nullptr; return; } snd_pcm_hw_params_get_period_size(hwparams, &frames_in_period, nullptr); start_mixer_thread(); }
// 声卡采集初始化 struct SoundInfo* sound_info_record_new() { struct SoundInfo *info = (struct SoundInfo*)malloc(sizeof(struct SoundInfo)); int rc; int dir = 0; info->channels = 2; info->frequency = 44100; rc = snd_pcm_open(&info->handle, "default", SND_PCM_STREAM_CAPTURE, 0); snd_pcm_hw_params_alloca(&info->params); rc = snd_pcm_hw_params_any(info->handle, info->params); rc = snd_pcm_hw_params_set_access(info->handle, info->params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(info->handle, info->params, SND_PCM_FORMAT_S16_LE); rc = snd_pcm_hw_params_set_channels(info->handle, info->params, info->channels); unsigned int val = info->frequency; rc = snd_pcm_hw_params_set_rate_near(info->handle, info->params, &val, &dir); rc = snd_pcm_hw_params(info->handle, info->params); info->frames = 32;//"frames"=channel*size/8=4, frames = "frames"*8 one period contains 8 "frames" snd_pcm_hw_params_set_period_size_near(info->handle, info->params, &info->frames, &dir); rc = snd_pcm_hw_params(info->handle, info->params); snd_pcm_hw_params_get_period_size(info->params, &info->frames, &dir); info->bufferSize = info->frames * 4; info->buffer = (char*) malloc(info->bufferSize); snd_pcm_hw_params_get_period_time(info->params, &val, &dir); memset(info->buffer, 0, info->bufferSize); return info; }
optional<int> AudioOutputDeviceAlsa::ParameterFragmentSize::DefaultAsInt(std::map<String,String> Parameters) { if (!Parameters.count("CARD")) return optional<int>::nothing; // obtain information from given sound card ParameterCard card(Parameters["CARD"]); String pcm_name = "hw:" + card.ValueAsString(); snd_pcm_t* pcm_handle = NULL; if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing; snd_pcm_hw_params_t* hwparams; snd_pcm_hw_params_alloca(&hwparams); if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { snd_pcm_close(pcm_handle); return optional<int>::nothing; } snd_pcm_uframes_t size = 128; if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &size, NULL) < 0) { snd_pcm_close(pcm_handle); return optional<int>::nothing; } snd_pcm_close(pcm_handle); return size; }
/** * This method will open the given device so that it can be accessed. */ void AudioInterface::open() { int rc; // This variable is to be used to store the return code from various calls. int dir; /* Open PCM device. */ snd_pcm_open(&handle, this->deviceName, this->direction, 0); /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, this->channels); // Set the sampling rate appropriately. snd_pcm_hw_params_set_rate_near(handle, params, &(this->samplingRate), &dir); /* Set period size to the given number of frames. */ 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); } }
static snd_pcm_t * bg_alsa_open(const char * card, gavl_audio_format_t * format, snd_pcm_stream_t stream, gavl_time_t buffer_time, int * convert_4_3) { unsigned int i_tmp; int dir, err; snd_pcm_hw_params_t *hw_params = NULL; // snd_pcm_sw_params_t *sw_params = NULL; snd_pcm_t *ret = NULL; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size_min = 0; snd_pcm_uframes_t period_size_max = 0; snd_pcm_uframes_t buffer_size_min = 0; snd_pcm_uframes_t buffer_size_max = 0; /* We open in non blocking mode so our process won't hang if the card is busy */ if((err = snd_pcm_open(&ret, card, stream, // SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_CAPTURE SND_PCM_NONBLOCK // SND_PCM_ASYNC ) < 0)) { ret = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_open failed for device %s (%s)", card, snd_strerror(err)); goto fail; } /* Now, set blocking mode */ snd_pcm_nonblock(ret, 0); if(snd_pcm_hw_params_malloc(&hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_malloc failed"); goto fail; } if(snd_pcm_hw_params_any(ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_any failed"); goto fail; } /* Interleave mode */ if(snd_pcm_hw_params_set_access(ret, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_access failed"); goto fail; } else format->interleave_mode = GAVL_INTERLEAVE_ALL; /* Sample format */ switch(format->sample_format) { case GAVL_SAMPLE_S8: case GAVL_SAMPLE_U8: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S8) < 0) // if(1) { /* Soundcard support no 8-bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else format->sample_format = GAVL_SAMPLE_S8; break; case GAVL_SAMPLE_S16: case GAVL_SAMPLE_U16: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; break; case GAVL_SAMPLE_S32: #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; break; case GAVL_SAMPLE_FLOAT: case GAVL_SAMPLE_DOUBLE: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_FLOAT) < 0) { #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; } else format->sample_format = GAVL_SAMPLE_FLOAT; break; case GAVL_SAMPLE_NONE: goto fail; break; } /* Channels */ if(snd_pcm_hw_params_set_channels(ret, hw_params, format->num_channels) < 0) { if(format->num_channels == 1) /* Mono doesn't work, try stereo */ { if(snd_pcm_hw_params_set_channels(ret, hw_params, 2) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } else { format->num_channels = 2; format->channel_locations[0] = GAVL_CHID_FRONT_LEFT; format->channel_locations[1] = GAVL_CHID_FRONT_RIGHT; } } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } } /* Switch off driver side resampling */ #if SND_LIB_VERSION >= 0x010009 snd_pcm_hw_params_set_rate_resample(ret, hw_params, 0); #endif /* Samplerate */ i_tmp = format->samplerate; if(snd_pcm_hw_params_set_rate_near(ret, hw_params, &i_tmp, 0) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_rate_near failed"); goto fail; } if(format->samplerate != i_tmp) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Samplerate %d not supported by device %s, using %d", format->samplerate, card, i_tmp); } format->samplerate = i_tmp; dir = 0; /* Buffer size */ snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min); snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max); dir=0; snd_pcm_hw_params_get_period_size_min(hw_params, &period_size_min,&dir); dir=0; snd_pcm_hw_params_get_period_size_max(hw_params, &period_size_max,&dir); buffer_size = gavl_time_to_samples(format->samplerate, buffer_time); if(buffer_size > buffer_size_max) buffer_size = buffer_size_max; if(buffer_size < buffer_size_min) buffer_size = buffer_size_min; period_size = buffer_size / 8; buffer_size = period_size * 8; dir = 0; if(snd_pcm_hw_params_set_period_size_near(ret, hw_params, &period_size, &dir) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_period_size failed"); goto fail; } dir = 0; snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir); dir = 0; if(snd_pcm_hw_params_set_buffer_size_near(ret, hw_params, &buffer_size) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_buffer_size failed"); goto fail; } snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size); format->samples_per_frame = period_size; /* Write params to card */ if(snd_pcm_hw_params (ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params failed"); goto fail; } snd_pcm_hw_params_free(hw_params); gavl_set_channel_setup(format); // gavl_audio_format_dump(format); return ret; fail: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Alsa initialization failed"); if(ret) snd_pcm_close(ret); if(hw_params) snd_pcm_hw_params_free(hw_params); return NULL; }
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 // 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 */ 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; }
static pj_status_t open_capture (struct alsa_stream* stream, const pjmedia_aud_param *param) { snd_pcm_hw_params_t* params; snd_pcm_format_t format; int result; unsigned int rate; snd_pcm_uframes_t tmp_buf_size; snd_pcm_uframes_t tmp_period_size; if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt) return PJMEDIA_EAUD_INVDEV; /* Open PCM for capture */ PJ_LOG (5,(THIS_FILE, "open_capture: Open capture device '%s'", stream->af->devs[param->rec_id].name)); result = snd_pcm_open (&stream->ca_pcm, stream->af->devs[param->rec_id].name, SND_PCM_STREAM_CAPTURE, 0); if (result < 0) return PJMEDIA_EAUD_SYSERR; /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca (¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any (stream->ca_pcm, params); /* Set interleaved mode */ snd_pcm_hw_params_set_access (stream->ca_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Set format */ switch (param->bits_per_sample) { case 8: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S8")); format = SND_PCM_FORMAT_S8; break; case 16: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE")); format = SND_PCM_FORMAT_S16_LE; break; case 24: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S24_LE")); format = SND_PCM_FORMAT_S24_LE; break; case 32: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S32_LE")); format = SND_PCM_FORMAT_S32_LE; break; default: TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE")); format = SND_PCM_FORMAT_S16_LE; break; } snd_pcm_hw_params_set_format (stream->ca_pcm, params, format); /* Set number of channels */ TRACE_((THIS_FILE, "open_capture: set channels: %d", param->channel_count)); snd_pcm_hw_params_set_channels (stream->ca_pcm, params, param->channel_count); /* Set clock rate */ rate = param->clock_rate; TRACE_((THIS_FILE, "open_capture: set clock rate: %d", rate)); snd_pcm_hw_params_set_rate_near (stream->ca_pcm, params, &rate, NULL); TRACE_((THIS_FILE, "open_capture: clock rate set to: %d", rate)); /* Set period size to samples_per_frame frames. */ stream->ca_frames = (snd_pcm_uframes_t) param->samples_per_frame / param->channel_count; TRACE_((THIS_FILE, "open_capture: set period size: %d", stream->ca_frames)); tmp_period_size = stream->ca_frames; snd_pcm_hw_params_set_period_size_near (stream->ca_pcm, params, &tmp_period_size, NULL); TRACE_((THIS_FILE, "open_capture: period size set to: %d", tmp_period_size)); /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) tmp_buf_size = (rate / 1000) * param->input_latency_ms; else tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY; snd_pcm_hw_params_set_buffer_size_near (stream->ca_pcm, params, &tmp_buf_size); stream->param.input_latency_ms = tmp_buf_size / (rate / 1000); /* Set our buffer */ stream->ca_buf_size = stream->ca_frames * param->channel_count * (param->bits_per_sample/8); stream->ca_buf = (char*) pj_pool_alloc (stream->pool, stream->ca_buf_size); TRACE_((THIS_FILE, "open_capture: buffer size set to: %d", (int)tmp_buf_size)); TRACE_((THIS_FILE, "open_capture: capture_latency set to: %d ms", (int)stream->param.input_latency_ms)); /* Activate the parameters */ result = snd_pcm_hw_params (stream->ca_pcm, params); if (result < 0) { snd_pcm_close (stream->ca_pcm); return PJMEDIA_EAUD_SYSERR; } PJ_LOG (5,(THIS_FILE, "Opened device alsa(%s) for capture, sample rate=%d" ", ch=%d, bits=%d, period size=%d frames, latency=%d ms", stream->af->devs[param->rec_id].name, rate, param->channel_count, param->bits_per_sample, stream->ca_frames, (int)stream->param.input_latency_ms)); return PJ_SUCCESS; }
int main(int argc, char *argv[]) { int32_t dwLoopsToRecord; int32_t dwStatus; int32_t dwAudioBufferSize; snd_pcm_t *AlsaHandle; snd_pcm_hw_params_t *AlsaParams; uint32_t dwSamplingRate; int32_t dwDirection; snd_pcm_uframes_t AlsaFrames; int8_t *bAudioBuffer; uint32_t dwChannels; wave_t WavFile; /* confirm there are enough parameters */ if(argc < 4) { printf("Usage: alsa_record <interface> <sampling_rate> <channels>"); exit(1); } printf("Alsa Record Opening device: %s\n",argv[1]); /* Open PCM device for recording (capture). */ dwStatus = snd_pcm_open(&AlsaHandle, argv[1], SND_PCM_STREAM_CAPTURE, 0); if (dwStatus < 0) { fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(dwStatus)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&AlsaParams); /* Fill it in with default values. */ snd_pcm_hw_params_any(AlsaHandle, AlsaParams); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(AlsaHandle, AlsaParams, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(AlsaHandle, AlsaParams, SND_PCM_FORMAT_S16_LE); /* Get the channels from the parameter */ dwChannels = atoi(argv[3]); printf("Alsa Record Recording %d channels\n",dwChannels); /* assign the channels for the wav file */ WavFile.wChannels = dwChannels; /* set channels to ALSA */ snd_pcm_hw_params_set_channels(AlsaHandle, AlsaParams, dwChannels); /* bits/second sampling rate */ dwSamplingRate = atoi(argv[2]); printf("Alsa Record Sampling rate: %i\n", dwSamplingRate); /* Set the sampling rate for the wav file */ WavFile.dwSampleRate = dwSamplingRate; /* Set the sampling rate to ASLA */ snd_pcm_hw_params_set_rate_near(AlsaHandle, AlsaParams, &dwSamplingRate, &dwDirection); /* Set period size to 32 frames. */ AlsaFrames = 32; snd_pcm_hw_params_set_period_size_near(AlsaHandle, AlsaParams, &AlsaFrames, &dwDirection); /* Write the parameters to the driver */ dwStatus = snd_pcm_hw_params(AlsaHandle, AlsaParams); if (dwStatus < 0) { fprintf(stderr,"unable to set hw parameters: %s\n",snd_strerror(dwStatus)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(AlsaParams, &AlsaFrames, &dwDirection); /* 2 bytes/sample, 2 channels */ dwAudioBufferSize = AlsaFrames * 2 * dwChannels; bAudioBuffer = (int8_t *) malloc(dwAudioBufferSize); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(AlsaParams, &dwSamplingRate, &dwDirection); /* Will record 5 seconds, get the amount of frames required */ dwLoopsToRecord = TIME_TO_RECORD_IN_US / dwSamplingRate; printf("SoundCard enabled and configured...\n"); printf("Opening output file\n"); /* Open the file and configure the wav header */ WavFile.dwWaveFileDescriptor = open("audio_mic.wav", O_WRONLY|O_CREAT,S_IRUSR|S_IRGRP|S_IROTH); WavFile.dwSeconds = TIME_TO_RECORD_IN_S; WavBuilder_vfnSetHeader(&WavFile); printf("Recording\n"); while (dwLoopsToRecord) { dwLoopsToRecord--; /* Read an audio frame */ dwStatus = snd_pcm_readi(AlsaHandle, bAudioBuffer, AlsaFrames); if (dwStatus == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(AlsaHandle); } else if (dwStatus < 0) { fprintf(stderr,"error from read: %s\n",snd_strerror(dwStatus)); } else if (dwStatus != (int32_t)AlsaFrames) { fprintf(stderr, "short read, read %d AlsaFrames\n", dwStatus); } /* Take the buffer and write it to the file */ WavBuilder_vfnWriteData(&WavFile,bAudioBuffer, dwAudioBufferSize); } printf("Done\n"); /* Once everything is done, close and release all resources */ snd_pcm_drain(AlsaHandle); snd_pcm_close(AlsaHandle); close(WavFile.dwWaveFileDescriptor); free(bAudioBuffer); return 0; }
eBool tfAlsa::openDevice(const eChar *device, eU32 freq, eU32 bits, eU32 channels) { eInt err = 0; if (device == eNULL) return eFALSE; printf ("opening device '%s' for playback\n", device); if ((err = snd_pcm_open (&m_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device '%s' for playback(%s)\n", device, snd_strerror (err)); return eFALSE; } snd_pcm_hw_params_t *hw_params; snd_pcm_format_t format; snd_pcm_uframes_t buffer_size = BUFFERSIZE; snd_pcm_uframes_t period_size = PERIODSIZE; printf("setting device to %i hz %i bits %i channels\n", freq, bits, channels); if (bits == 16) format = SND_PCM_FORMAT_S16_LE; else format = SND_PCM_FORMAT_S8; if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_any (m_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_access (m_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_format (m_handle, hw_params, format)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_rate_near (m_handle, hw_params, (unsigned int *)&freq, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_channels (m_handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_buffer_size_near (m_handle, hw_params, &buffer_size)) < 0) { fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params_set_period_size_near (m_handle, hw_params, &period_size, NULL)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)); return false; } if ((err = snd_pcm_hw_params (m_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); return false; } snd_pcm_hw_params_free (hw_params); return eTRUE; }
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 recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_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); loops = 5000000 / val; while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, 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); } rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
snd_pcm_t * open_capture (char *name,unsigned int set_rate, int channel, int bit) { snd_pcm_hw_params_t* params; snd_pcm_format_t format; int result; snd_pcm_uframes_t tmp_buf_size; snd_pcm_uframes_t tmp_period_size; snd_pcm_t *ca_pcm; /* Open PCM for capture */ result = snd_pcm_open (&ca_pcm,name,SND_PCM_STREAM_CAPTURE,0); if (result < 0) printf("error \n"); /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca (¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any (ca_pcm, params); /* Set interleaved mode */ snd_pcm_hw_params_set_access (ca_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Set format */ format = SND_PCM_FORMAT_S16_LE; switch(bit/8){ case 1:format=SND_PCM_FORMAT_U8; break ; case 3:format=SND_PCM_FORMAT_S24_LE; break ; } snd_pcm_hw_params_set_format (ca_pcm, params, format); /* Set number of channels */ snd_pcm_hw_params_set_channels (ca_pcm, params,channel); /* Set clock rate */ snd_pcm_hw_params_set_rate_near (ca_pcm, params, &set_rate, NULL); /* Set the sound device buffer size and latency */ tmp_buf_size = 4096;//(set_rate / 1000) * input_latency_ms; //设置缓冲区 snd_pcm_hw_params_set_buffer_size_near (ca_pcm, params, &tmp_buf_size); input_latency_ms = tmp_buf_size / (set_rate / 1000); /* Set period size to samples_per_frame frames. */ //ca_frames = (snd_pcm_uframes_t) samples_per_frame /channel; tmp_period_size = tmp_buf_size/8;//ca_frames; //设置周期 snd_pcm_hw_params_set_period_size_near (ca_pcm, params, &tmp_period_size, NULL); /* Set our buffer */ ca_buf_size = tmp_period_size/2;//ca_frames * channel * (bits_per_sample/8); printf("ca_buf_size is %d\n",ca_buf_size); ca_buf = (u_char *)malloc(ca_buf_size); /* Activate the parameters */ result = snd_pcm_hw_params (ca_pcm, params); if (result < 0) { snd_pcm_close (ca_pcm); } return ca_pcm; }
static int drvHostALSAAudioOpen(bool fIn, PALSAAUDIOSTREAMCFG pCfgReq, PALSAAUDIOSTREAMCFG pCfgObt, snd_pcm_t **pphPCM) { snd_pcm_t *phPCM = NULL; int rc; unsigned int cChannels = pCfgReq->nchannels; unsigned int uFreq = pCfgReq->freq; snd_pcm_uframes_t obt_buffer_size; do { const char *pszDev = fIn ? s_ALSAConf.pcm_name_in : s_ALSAConf.pcm_name_out; if (!pszDev) { LogRel(("ALSA: Invalid or no %s device name set\n", fIn ? "input" : "output")); rc = VERR_INVALID_PARAMETER; break; } int err = snd_pcm_open(&phPCM, pszDev, fIn ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { LogRel(("ALSA: Failed to open \"%s\" as %s: %s\n", pszDev, fIn ? "ADC" : "DAC", snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } snd_pcm_hw_params_t *pHWParms; snd_pcm_hw_params_alloca(&pHWParms); /** @todo Check for successful allocation? */ err = snd_pcm_hw_params_any(phPCM, pHWParms); if (err < 0) { LogRel(("ALSA: Failed to initialize hardware parameters: %s\n", snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } err = snd_pcm_hw_params_set_access(phPCM, pHWParms, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { LogRel(("ALSA: Failed to set access type: %s\n", snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } err = snd_pcm_hw_params_set_format(phPCM, pHWParms, pCfgReq->fmt); if (err < 0) { LogRel(("ALSA: Failed to set audio format to %d: %s\n", pCfgReq->fmt, snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } err = snd_pcm_hw_params_set_rate_near(phPCM, pHWParms, &uFreq, 0); if (err < 0) { LogRel(("ALSA: Failed to set frequency to %dHz: %s\n", pCfgReq->freq, snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } err = snd_pcm_hw_params_set_channels_near(phPCM, pHWParms, &cChannels); if (err < 0) { LogRel(("ALSA: Failed to set number of channels to %d\n", pCfgReq->nchannels)); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } if ( cChannels != 1 && cChannels != 2) { LogRel(("ALSA: Number of audio channels (%u) not supported\n", cChannels)); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } unsigned int period_size = pCfgReq->period_size; unsigned int buffer_size = pCfgReq->buffer_size; if ( !((fIn && s_ALSAConf.size_in_usec_in) || (!fIn && s_ALSAConf.size_in_usec_out))) { if (!buffer_size) { buffer_size = DEFAULT_BUFFER_SIZE; period_size = DEFAULT_PERIOD_SIZE; } } if (buffer_size) { if ( ( fIn && s_ALSAConf.size_in_usec_in) || (!fIn && s_ALSAConf.size_in_usec_out)) { if (period_size) { err = snd_pcm_hw_params_set_period_time_near(phPCM, pHWParms, &period_size, 0); if (err < 0) { LogRel(("ALSA: Failed to set period time %d\n", pCfgReq->period_size)); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } } err = snd_pcm_hw_params_set_buffer_time_near(phPCM, pHWParms, &buffer_size, 0); if (err < 0) { LogRel(("ALSA: Failed to set buffer time %d\n", pCfgReq->buffer_size)); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } } else { snd_pcm_uframes_t period_size_f = (snd_pcm_uframes_t)period_size; snd_pcm_uframes_t buffer_size_f = (snd_pcm_uframes_t)buffer_size; snd_pcm_uframes_t minval; if (period_size_f) { minval = period_size_f; int dir = 0; err = snd_pcm_hw_params_get_period_size_min(pHWParms, &minval, &dir); if (err < 0) { LogRel(("ALSA: Could not determine minimal period size\n")); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } else { LogFunc(("Minimal period size is: %ld\n", minval)); if (period_size_f < minval) { if ( ( fIn && s_ALSAConf.period_size_in_overriden) || (!fIn && s_ALSAConf.period_size_out_overriden)) { LogFunc(("Period size %RU32 is less than minimal period size %RU32\n", period_size_f, minval)); } period_size_f = minval; } } err = snd_pcm_hw_params_set_period_size_near(phPCM, pHWParms, &period_size_f, 0); LogFunc(("Period size is: %RU32\n", period_size_f)); if (err < 0) { LogRel(("ALSA: Failed to set period size %d (%s)\n", period_size_f, snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } } /* Calculate default buffer size here since it might have been changed * in the _near functions */ buffer_size_f = 4 * period_size_f; minval = buffer_size_f; err = snd_pcm_hw_params_get_buffer_size_min(pHWParms, &minval); if (err < 0) { LogRel(("ALSA: Could not retrieve minimal buffer size\n")); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } else { LogFunc(("Minimal buffer size is: %RU32\n", minval)); if (buffer_size_f < minval) { if ( ( fIn && s_ALSAConf.buffer_size_in_overriden) || (!fIn && s_ALSAConf.buffer_size_out_overriden)) { LogFunc(("Buffer size %RU32 is less than minimal buffer size %RU32\n", buffer_size_f, minval)); } buffer_size_f = minval; } } err = snd_pcm_hw_params_set_buffer_size_near(phPCM, pHWParms, &buffer_size_f); LogFunc(("Buffer size is: %RU32\n", buffer_size_f)); if (err < 0) { LogRel(("ALSA: Failed to set buffer size %d: %s\n", buffer_size_f, snd_strerror(err))); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } } } else LogFunc(("Warning: Buffer size is not set\n")); err = snd_pcm_hw_params(phPCM, pHWParms); if (err < 0) { LogRel(("ALSA: Failed to apply audio parameters\n")); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } err = snd_pcm_hw_params_get_buffer_size(pHWParms, &obt_buffer_size); if (err < 0) { LogRel(("ALSA: Failed to get buffer size\n")); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } snd_pcm_uframes_t obt_period_size; int dir = 0; err = snd_pcm_hw_params_get_period_size(pHWParms, &obt_period_size, &dir); if (err < 0) { LogRel(("ALSA: Failed to get period size\n")); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } LogFunc(("Freq=%dHz, period size=%RU32, buffer size=%RU32\n", pCfgReq->freq, obt_period_size, obt_buffer_size)); err = snd_pcm_prepare(phPCM); if (err < 0) { LogRel(("ALSA: Could not prepare hPCM %p\n", (void *)phPCM)); rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ break; } if ( !fIn && s_ALSAConf.threshold) { unsigned uShift; rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift); if (RT_SUCCESS(rc)) { int bytes_per_sec = uFreq << (cChannels == 2) << uShift; snd_pcm_uframes_t threshold = (s_ALSAConf.threshold * bytes_per_sec) / 1000; rc = drvHostALSAAudioSetThreshold(phPCM, threshold); } } else rc = VINF_SUCCESS; } while (0); if (RT_SUCCESS(rc)) { pCfgObt->fmt = pCfgReq->fmt; pCfgObt->nchannels = cChannels; pCfgObt->freq = uFreq; pCfgObt->samples = obt_buffer_size; *pphPCM = phPCM; } else drvHostALSAAudioClose(&phPCM); LogFlowFuncLeaveRC(rc); return rc; }
static void set_params(void) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size; int err; size_t n; snd_pcm_uframes_t xfer_align; unsigned int rate; snd_pcm_uframes_t start_threshold, stop_threshold; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(handle, params); if (err < 0) { error(_("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) { error(_("Access type not available")); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_format(handle, params, hwparams.format); if (err < 0) { error(_("Sample format non available")); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); if (err < 0) { error(_("Channels count non available")); exit(EXIT_FAILURE); } #if 0 err = snd_pcm_hw_params_set_periods_min(handle, params, 2); assert(err >= 0); #endif rate = hwparams.rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0); assert(err >= 0); if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) { if (!quiet_mode) { char plugex[64]; const char *pcmname = snd_pcm_name(handle); fprintf(stderr, _("Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"), rate, hwparams.rate); if (! pcmname || strchr(snd_pcm_name(handle), ':')) *plugex = 0; else snprintf(plugex, sizeof(plugex), "(-Dplug:%s)", snd_pcm_name(handle)); fprintf(stderr, _(" please, try the plug plugin %s\n"), plugex); } } rate = hwparams.rate; if (buffer_time == 0 && buffer_frames == 0) { err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); assert(err >= 0); if (buffer_time > 500000) buffer_time = 500000; } if (period_time == 0 && period_frames == 0) { if (buffer_time > 0) period_time = buffer_time / 4; else period_frames = buffer_frames / 4; } if (period_time > 0) err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0); else err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_frames, 0); assert(err >= 0); if (buffer_time > 0) { err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); } else { err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_frames); } assert(err >= 0); err = snd_pcm_hw_params(handle, params); if (err < 0) { error(_("Unable to install hw params:")); snd_pcm_hw_params_dump(params, log); 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) { error(_("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_get_xfer_align(swparams, &xfer_align); if (err < 0) { error(_("Unable to obtain xfer align\n")); exit(EXIT_FAILURE); } if (sleep_min) xfer_align = 1; err = snd_pcm_sw_params_set_sleep_min(handle, swparams, sleep_min); assert(err >= 0); if (avail_min < 0) n = chunk_size; else n = (double) rate * avail_min / 1000000; err = snd_pcm_sw_params_set_avail_min(handle, swparams, n); // round up to closest transfer boundary n = (buffer_size / xfer_align) * xfer_align; start_threshold = n; if (start_threshold < 1) start_threshold = 1; if (start_threshold > n) start_threshold = n; err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); assert(err >= 0); stop_threshold = buffer_size; err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); assert(err >= 0); err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align); assert(err >= 0); if (snd_pcm_sw_params(handle, swparams) < 0) { error(_("unable to install sw params:")); snd_pcm_sw_params_dump(swparams, log); exit(EXIT_FAILURE); } bits_per_sample = snd_pcm_format_physical_width(hwparams.format); bits_per_frame = bits_per_sample * hwparams.channels; chunk_bytes = chunk_size * bits_per_frame / 8; audiobuf = realloc(audiobuf, chunk_bytes); if (audiobuf == NULL) { error(_("not enough memory")); exit(EXIT_FAILURE); } // fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size); }