static void alsa_fill_w (snd_pcm_t *pcm_handle) { snd_pcm_hw_params_t *hwparams=NULL; int channels; snd_pcm_uframes_t buffer_size; int buffer_size_bytes; void *buffer; /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_current(pcm_handle, hwparams); /* get channels */ snd_pcm_hw_params_get_channels (hwparams, &channels); /* get buffer size */ snd_pcm_hw_params_get_buffer_size (hwparams, &buffer_size); /* fill half */ buffer_size /= 2; /* allocate buffer assuming 2 bytes per sample */ buffer_size_bytes = buffer_size * channels * 2; buffer = alloca (buffer_size_bytes); memset (buffer, 0, buffer_size_bytes); /* write data */ snd_pcm_writei(pcm_handle, buffer, buffer_size); }
result alsa_init(Soloud *aSoloud, unsigned int aFlags, unsigned int aSamplerate, unsigned int aBuffer, unsigned int aChannels) { ALSAData *data = new ALSAData; memset(data, 0, sizeof(ALSAData)); aSoloud->mBackendData = data; aSoloud->mBackendCleanupFunc = alsaCleanup; data->samples = aBuffer; data->channels = 2; data->soloud = aSoloud; int rc; snd_pcm_t *handle; rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { return UNKNOWN_ERROR; } data->alsaDeviceHandle = handle; snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 2); snd_pcm_hw_params_set_buffer_size(handle, params, aBuffer); unsigned int val = aSamplerate; int dir = 0; rc = snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); if (rc < 0) { return UNKNOWN_ERROR; } rc = snd_pcm_hw_params(handle, params); if (rc < 0) { return UNKNOWN_ERROR; } snd_pcm_hw_params_get_rate(params, &val, &dir); aSamplerate = val; snd_pcm_hw_params_get_channels(params, &val); data->channels = val; data->buffer = new float[data->samples*data->channels]; data->sampleBuffer = new short[data->samples*data->channels]; aSoloud->postinit(aSamplerate, data->samples * data->channels, aFlags, 2); data->threadHandle = Thread::createThread(alsaThread, data); if (0 == data->threadHandle) { return UNKNOWN_ERROR; } aSoloud->mBackendString = "ALSA"; return 0; }
static int ste_iop_hwparams(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) { int err = 0; int direction; ste_iop_t *ste_iop = io->private_data; /* Get and print HW params */ /* PCM format */ err = snd_pcm_hw_params_get_format(params, &ste_iop->hwparams.pcm_format); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to get HW param PCM format: %s\n", snd_strerror(err)); return err; } /* PCM access mode */ err = snd_pcm_hw_params_get_access(params, &ste_iop->hwparams.pcm_access); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to get HW param PCM Access mode: %s\n", snd_strerror(err)); return err; } /* PCM number of channels */ err = snd_pcm_hw_params_get_channels(params, &ste_iop->hwparams.pcm_channels); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to get HW param PCM number of channels: %s\n", snd_strerror(err)); return err; } /* Sample Rate */ err = snd_pcm_hw_params_get_rate(params, &ste_iop->hwparams.pcm_rate, &direction); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to get HW param PCM Sample Rate: %s\n", snd_strerror(err)); return err; } ste_iop->bufsz = ste_iop->hwparams.pcm_rate * 32 / 1000 * 2 * ste_iop->hwparams.pcm_channels; /* Period time */ err = snd_pcm_hw_params_get_period_time(params, &ste_iop->hwparams.pcm_period_time, &direction); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to get HW param PCM period time: %s\n", snd_strerror(err)); return err; } return 0; }
AudioSourceNix::AudioSourceNix(int c, int r) : AudioSource(c, r) { int err; unsigned int ap_rate = rate; unsigned int ap_chan = channels; err = snd_pcm_open(&device, ADDR, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { g2g = PR_FALSE; return; } err = snd_pcm_hw_params_malloc(¶ms); if (err < 0) { g2g = PR_FALSE; return; } err = snd_pcm_hw_params_any(device, params); if (err < 0) { g2g = PR_FALSE; return; } err = snd_pcm_hw_params_set_access( device, params, SND_PCM_ACCESS_RW_INTERLEAVED ); if (err < 0) { g2g = PR_FALSE; return; } err = snd_pcm_hw_params_set_format( device, params, SND_PCM_FORMAT_S16_LE ); if (err < 0) { g2g = PR_FALSE; return; } /* For rate and channels if we don't get * what we want, that's too bad */ err = snd_pcm_hw_params_set_rate_near( device, params, &ap_rate, 0 ); if (err < 0) { err = snd_pcm_hw_params_get_rate( params, &ap_rate, 0 ); if (err < 0) { g2g = PR_FALSE; return; } } err = snd_pcm_hw_params_set_channels( device, params, ap_chan ); if (err < 0) { err = snd_pcm_hw_params_get_channels( params, &ap_chan ); if (err < 0) { g2g = PR_FALSE; return; } } g2g = PR_TRUE; rec = PR_FALSE; rate = ap_rate; channels = ap_chan; snd_pcm_close(device); }
int snd_send(FILE * fp, size_t n) { snd_pcm_format_t format; unsigned int nchannels; snd_pcm_uframes_t period; snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_current(pcm, params); snd_pcm_hw_params_get_format(params, &format); snd_pcm_hw_params_get_channels(params, &nchannels); snd_pcm_hw_params_get_period_size(params, &period, 0); int framesize = snd_pcm_format_width(format) / 8 * nchannels; unsigned char buf[period * framesize * 128]; size_t l; while (n > sizeof(buf)) { if ((l = fread(buf, 1, sizeof(buf), fp))) { switch (snd_pcm_writei(pcm, buf, l / framesize)) { case -EBADF: return -1; case -EPIPE: #ifndef NDEBUG snd_pcm_recover(pcm, -EPIPE, 0); #else snd_pcm_prepare(pcm); #endif } } else goto EOS; n -= l; } if ((l = fread(buf, 1, n, fp))) snd_pcm_writei(pcm, buf, l / framesize); if (l < n) EOS:if (ftell(fp) > 0) eputs("Unexpected end of stream"); return snd_pcm_drain(pcm); }
void alsa_print_info(snd_pcm_t * handle, snd_pcm_hw_params_t * hwp) { printf("device [%s] opened with\n", snd_pcm_name(handle)); printf("\tstate=%s\n", snd_pcm_state_name(snd_pcm_state(handle))); unsigned int val, val2; snd_pcm_hw_params_get_access(hwp, (snd_pcm_access_t *) &val); printf("\taccess_type=%s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(hwp, (snd_pcm_format_t *) &val); printf("\tformat=%s\n", snd_pcm_format_name((snd_pcm_format_t) val) ); snd_pcm_hw_params_get_channels(hwp, &val); printf("\tchannels=%d\n", val); snd_pcm_hw_params_get_rate(hwp, &val, (int *) &val2); printf("\trate=%d fps\n", val); snd_pcm_hw_params_get_period_time(hwp, &val, (int *) &val2); printf("\tperiod_time=%d us\n", val); snd_pcm_uframes_t frames; snd_pcm_hw_params_get_period_size(hwp, &frames, (int *) &val2); printf("\tperiod_size=%d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_size(hwp, (snd_pcm_uframes_t *) &val); printf("\tbuffer_size=%d frames\n", val); snd_pcm_hw_params_get_periods(hwp, &val, (int *) &val2); printf("\tperiods_per_buffer=%d periods\n", val); }
int main() { int rc; snd_pcm_t* handle; snd_pcm_hw_params_t* params; unsigned int val; unsigned int val2; int dir; snd_pcm_uframes_t frames; if ( (rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { std::cerr << "unable to open pcm devices: " << snd_strerror(rc) << std::endl; exit(1); } 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); val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); if ( (rc = snd_pcm_hw_params(handle, params)) < 0) { std::cerr << "unable to set hw parameters: " << snd_strerror(rc) << std::endl; exit(1); } std::cout << "PCM handle name = " << snd_pcm_name(handle) << std::endl; std::cout << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle)) << std::endl; snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *)&val); std::cout << "access type = " << snd_pcm_access_name((snd_pcm_access_t)val) << std::endl; snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)(&val)); std::cout << "format = '" << snd_pcm_format_name((snd_pcm_format_t)val) << "' (" << snd_pcm_format_description((snd_pcm_format_t)val) << ")" << std::endl; snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val); std::cout << "subformat = '" << snd_pcm_subformat_name((snd_pcm_subformat_t)val) << "' (" << snd_pcm_subformat_description((snd_pcm_subformat_t)val) << ")" << std::endl; snd_pcm_hw_params_get_channels(params, &val); std::cout << "channels = " << val << std::endl; snd_pcm_hw_params_get_rate(params, &val, &dir); std::cout << "rate = " << val << " bps" << std::endl; snd_pcm_hw_params_get_period_time(params, &val, &dir); std::cout << "period time = " << val << " us" << std::endl; snd_pcm_hw_params_get_period_size(params, &frames, &dir); std::cout << "period size = " << static_cast<int>(frames) << " frames" << std::endl; snd_pcm_hw_params_get_buffer_time(params, &val, &dir); std::cout << "buffer time = " << val << " us" << std::endl; snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); std::cout << "buffer size = " << val << " frames" << std::endl; snd_pcm_hw_params_get_periods(params, &val, &dir); std::cout << "periods per buffer = " << val << " frames" << std::endl; snd_pcm_hw_params_get_rate_numden(params, &val, &val2); std::cout << "exact rate = " << val/val2 << " bps" << std::endl; val = snd_pcm_hw_params_get_sbits(params); std::cout << "significant bits = " << val << std::endl; snd_pcm_hw_params_get_tick_time(params, &val, &dir); std::cout << "tick time = " << val << " us" << std::endl; val = snd_pcm_hw_params_is_batch(params); std::cout << "is batch = " << val << std::endl; val = snd_pcm_hw_params_is_block_transfer(params); std::cout << "is block transfer = " << val << std::endl; val = snd_pcm_hw_params_is_double(params); std::cout << "is double = " << val << std::endl; val = snd_pcm_hw_params_is_half_duplex(params); std::cout << "is half duplex = " << val << std::endl; val = snd_pcm_hw_params_is_joint_duplex(params); std::cout << "is joint duplex = " << val << std::endl; val = snd_pcm_hw_params_can_overrange(params); std::cout << "can overrange = " << val << std::endl; val = snd_pcm_hw_params_can_mmap_sample_resolution(params); std::cout << "can mmap = " << val << std::endl; val = snd_pcm_hw_params_can_pause(params); std::cout << "can pause = " << val << std::endl; val = snd_pcm_hw_params_can_resume(params); std::cout << "can resume = " << val << std::endl; val = snd_pcm_hw_params_can_sync_start(params); std::cout << "can sync start = " << val << std::endl; snd_pcm_close(handle); return 0; }
int main() { int rc; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val, val2; int dir; snd_pcm_uframes_t frames; /* Open PCM device for playback. */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* 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); } /* Display information about the PCM interface */ printf("PCM handle name = '%s'\n", snd_pcm_name(handle)); printf("PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(handle))); snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val); printf("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(params, &val); printf("format = '%s' (%s)\n", snd_pcm_format_name((snd_pcm_format_t)val), snd_pcm_format_description( (snd_pcm_format_t)val)); snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val); printf("subformat = '%s' (%s)\n", snd_pcm_subformat_name((snd_pcm_subformat_t)val), snd_pcm_subformat_description( (snd_pcm_subformat_t)val)); snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); snd_pcm_hw_params_get_tick_time(params, &val, &dir); printf("tick time = %d us\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); snd_pcm_close(handle); return 0; }
int main(int argc, char **argv){ int i; int aver,val,val2; int16_t buf[BUFSIZE]; double d_buffer[BUFSIZE]; double pitch = 0.0; struct timespec before,after; struct pitch_tracker_params *settings; snd_pcm_uframes_t period_size = PERIOD_SIZE; //ALSA PCM configuration snd_pcm_t *handle; snd_pcm_hw_params_t *params; int dir,rc; snd_pcm_uframes_t frames; /* Open PCM device for capture */ rc = snd_pcm_open( &handle, "default" , SND_PCM_STREAM_CAPTURE , 0); if(rc < 0 ){ fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED); /* unsigned 16-bit format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate */ val = 44100; snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir); /* set size time*/ snd_pcm_hw_params_set_period_size_near(handle, params, &period_size , &dir); /* write configuration */ rc = snd_pcm_hw_params(handle,params); /*Display info*/ printf("PCM handle name = '%s'\n", snd_pcm_name(handle)); printf("PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(handle))); snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *) &val); printf("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(params, &val); printf("format = '%s' (%s)\n", snd_pcm_format_name((snd_pcm_format_t)val), snd_pcm_format_description( (snd_pcm_format_t)val)); snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val); printf("subformat = '%s' (%s)\n", snd_pcm_subformat_name((snd_pcm_subformat_t)val), snd_pcm_subformat_description( (snd_pcm_subformat_t)val)); snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); settings = open_pitch_tracker(); while(1){ rc = snd_pcm_readi(handle, buf, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } for( i = 0 ; i< BUFSIZE ; i++){ d_buffer[i] = (double) buf[i]; } pitch = compute_pitch(d_buffer, BUFSIZE, S16, settings ,ACCURACY); if( pitch != 0.0 ) printf("frequency -> %f\n",pitch); memset(buf,0,BUFSIZE); } close_pitch_tracker(&settings); snd_pcm_drain(handle); snd_pcm_close(handle); return 0; }
int alsa_hook_hw_params(alsa_hook_t alsa_hook, snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { struct alsa_hook_stream_s *stream; snd_pcm_format_t format; snd_pcm_uframes_t period_size; snd_pcm_access_t access; int dir, ret; alsa_hook_get_stream(alsa_hook, pcm, &stream); if (unlikely((ret = alsa_hook_lock_write(alsa_hook, stream)))) return ret; glc_log(alsa_hook->glc, GLC_DEBUG, "alsa_hook", "%p: creating/updating configuration for stream %d", stream->pcm, stream->id); /* extract information */ if (unlikely((ret = snd_pcm_hw_params_get_format(params, &format)) < 0)) goto err; stream->flags = 0; /* zero flags */ stream->format = pcm_fmt_to_glc_fmt(format); if (unlikely(!stream->format)) { glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook", "%p: unsupported audio format 0x%02x", stream->pcm, format); ret = ENOTSUP; goto err; } if (unlikely((ret = snd_pcm_hw_params_get_rate(params, &stream->rate, &dir)) < 0)) goto err; if (unlikely((ret = snd_pcm_hw_params_get_channels(params, &stream->channels)) < 0)) goto err; if (unlikely((ret = snd_pcm_hw_params_get_period_size(params, &period_size, NULL)) < 0)) goto err; if (unlikely((ret = snd_pcm_hw_params_get_access(params, &access)) < 0)) goto err; if ((access == SND_PCM_ACCESS_RW_INTERLEAVED) || (access == SND_PCM_ACCESS_MMAP_INTERLEAVED)) stream->flags |= GLC_AUDIO_INTERLEAVED; else if (access == SND_PCM_ACCESS_MMAP_COMPLEX) { stream->flags |= GLC_AUDIO_INTERLEAVED; /* convert to interleaved */ stream->complex = 1; /* do conversion */ } else { glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook", "%p: unsupported access mode 0x%02x", stream->pcm, access); ret = ENOTSUP; goto err; } glc_log(alsa_hook->glc, GLC_DEBUG, "alsa_hook", "%p: %d channels, rate %d, flags 0x%02x", stream->pcm, stream->channels, stream->rate, stream->flags); stream->fmt = 1; if (alsa_hook->started) { if (unlikely((ret = alsa_hook_stream_init(alsa_hook, stream)))) goto err; } alsa_hook_unlock_write(alsa_hook, stream); return 0; err: glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook", "%p: can't extract hardware configuration: %s (%d)", stream->pcm, snd_strerror(ret), ret); alsa_hook_unlock_write(alsa_hook, stream); return ret; }
static int palsa_set_hw_params (ddb_waveformat_t *fmt) { snd_pcm_hw_params_t *hw_params = NULL; int err = 0; memcpy (&plugin.fmt, fmt, sizeof (ddb_waveformat_t)); if (!plugin.fmt.channels) { // generic format plugin.fmt.bps = 16; plugin.fmt.is_float = 0; plugin.fmt.channels = 2; plugin.fmt.samplerate = 44100; plugin.fmt.channelmask = 3; } snd_pcm_nonblock(audio, 0); snd_pcm_drain (audio); snd_pcm_nonblock(audio, 1); if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); goto error; } if ((err = snd_pcm_hw_params_any (audio, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); goto error; } if ((err = snd_pcm_hw_params_set_access (audio, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); goto error; } snd_pcm_format_t sample_fmt; switch (plugin.fmt.bps) { case 8: sample_fmt = SND_PCM_FORMAT_S8; break; case 16: #if WORDS_BIGENDIAN sample_fmt = SND_PCM_FORMAT_S16_BE; #else sample_fmt = SND_PCM_FORMAT_S16_LE; #endif break; case 24: #if WORDS_BIGENDIAN sample_fmt = SND_PCM_FORMAT_S24_3BE; #else sample_fmt = SND_PCM_FORMAT_S24_3LE; #endif break; case 32: if (plugin.fmt.is_float) { #if WORDS_BIGENDIAN sample_fmt = SND_PCM_FORMAT_FLOAT_BE; #else sample_fmt = SND_PCM_FORMAT_FLOAT_LE; #endif } else { #if WORDS_BIGENDIAN sample_fmt = SND_PCM_FORMAT_S32_BE; #else sample_fmt = SND_PCM_FORMAT_S32_LE; #endif } break; } if ((err = snd_pcm_hw_params_set_format (audio, hw_params, sample_fmt)) < 0) { fprintf (stderr, "cannot set sample format to %d bps (error: %s), trying all supported formats\n", plugin.fmt.bps, snd_strerror (err)); int fmt_cnt[] = { 16, 24, 32, 32, 8 }; #if WORDS_BIGENDIAN int fmt[] = { SND_PCM_FORMAT_S16_BE, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_S32_BE, SND_PCM_FORMAT_FLOAT_BE, SND_PCM_FORMAT_S8, -1 }; #else int fmt[] = { SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_FORMAT_S8, -1 }; #endif // 1st try formats with higher bps int i = 0; for (i = 0; fmt[i] != -1; i++) { if (fmt[i] != sample_fmt && fmt_cnt[i] > plugin.fmt.bps) { if (snd_pcm_hw_params_set_format (audio, hw_params, fmt[i]) >= 0) { fprintf (stderr, "Found compatible format %d bps\n", fmt_cnt[i]); sample_fmt = fmt[i]; break; } } } if (fmt[i] == -1) { // next try formats with lower bps i = 0; for (i = 0; fmt[i] != -1; i++) { if (fmt[i] != sample_fmt && fmt_cnt[i] < plugin.fmt.bps) { if (snd_pcm_hw_params_set_format (audio, hw_params, fmt[i]) >= 0) { fprintf (stderr, "Found compatible format %d bps\n", fmt_cnt[i]); sample_fmt = fmt[i]; break; } } } } if (fmt[i] == -1) { fprintf (stderr, "Fallback format could not be found\n"); goto error; } } snd_pcm_hw_params_get_format (hw_params, &sample_fmt); trace ("chosen sample format: %04Xh\n", (int)sample_fmt); int val = plugin.fmt.samplerate; int ret = 0; if ((err = snd_pcm_hw_params_set_rate_resample (audio, hw_params, conf_alsa_resample)) < 0) { fprintf (stderr, "cannot setup resampling (%s)\n", snd_strerror (err)); goto error; } if ((err = snd_pcm_hw_params_set_rate_near (audio, hw_params, &val, &ret)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); goto error; } plugin.fmt.samplerate = val; trace ("chosen samplerate: %d Hz\n", val); int chanmin, chanmax; snd_pcm_hw_params_get_channels_min (hw_params, &chanmin); snd_pcm_hw_params_get_channels_max (hw_params, &chanmax); trace ("minchan: %d, maxchan: %d\n", chanmin, chanmax); int nchan = plugin.fmt.channels; if (nchan > chanmax) { nchan = chanmax; } else if (nchan < chanmin) { nchan = chanmin; } trace ("setting chan=%d\n", nchan); if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, nchan)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); } snd_pcm_hw_params_get_channels (hw_params, &nchan); trace ("alsa channels: %d\n", nchan); req_buffer_size = deadbeef->conf_get_int ("alsa.buffer", DEFAULT_BUFFER_SIZE); req_period_size = deadbeef->conf_get_int ("alsa.period", DEFAULT_PERIOD_SIZE); buffer_size = req_buffer_size; period_size = req_period_size; trace ("trying buffer size: %d frames\n", (int)buffer_size); trace ("trying period size: %d frames\n", (int)period_size); snd_pcm_hw_params_set_buffer_size_near (audio, hw_params, &buffer_size); snd_pcm_hw_params_set_period_size_near (audio, hw_params, &period_size, NULL); trace ("alsa buffer size: %d frames\n", (int)buffer_size); trace ("alsa period size: %d frames\n", (int)period_size); if ((err = snd_pcm_hw_params (audio, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); goto error; } plugin.fmt.is_float = 0; switch (sample_fmt) { case SND_PCM_FORMAT_S8: plugin.fmt.bps = 8; break; case SND_PCM_FORMAT_S16_BE: case SND_PCM_FORMAT_S16_LE: plugin.fmt.bps = 16; break; case SND_PCM_FORMAT_S24_3BE: case SND_PCM_FORMAT_S24_3LE: plugin.fmt.bps = 24; break; case SND_PCM_FORMAT_S32_BE: case SND_PCM_FORMAT_S32_LE: plugin.fmt.bps = 32; break; case SND_PCM_FORMAT_FLOAT_LE: case SND_PCM_FORMAT_FLOAT_BE: plugin.fmt.bps = 32; plugin.fmt.is_float = 1; break; } trace ("chosen bps: %d (%s)\n", plugin.fmt.bps, plugin.fmt.is_float ? "float" : "int"); plugin.fmt.channels = nchan; plugin.fmt.channelmask = 0; if (nchan == 1) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT; } if (nchan == 2) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT; } if (nchan == 3) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_LOW_FREQUENCY; } if (nchan == 4) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT; } if (nchan == 5) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER; } if (nchan == 6) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_LOW_FREQUENCY; } if (nchan == 7) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_SIDE_LEFT | DDB_SPEAKER_SIDE_RIGHT; } if (nchan == 8) { plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_SIDE_LEFT | DDB_SPEAKER_SIDE_RIGHT | DDB_SPEAKER_LOW_FREQUENCY; } error: if (err < 0) { memset (&plugin.fmt, 0, sizeof (ddb_waveformat_t)); } if (hw_params) { snd_pcm_hw_params_free (hw_params); } return err; }
/* ------- PCM INITS --------------------------------- */ static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params,int *chs) { #ifndef ALSAAPI9 unsigned int rrate; int err, dir; int channels_allocated = 0; /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { check_error(err,"Broken configuration: no configurations available"); return err; } /* set the nointerleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); if (err >= 0) { #ifdef ALSAMM_DEBUG if(sys_verbose) post("Access type %s available","SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); #endif } else{ check_error(err,"No Accesstype SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, ALSAMM_FORMAT); if (err < 0) { check_error(err,"Sample format not available for playback"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Setting format to %s",snd_pcm_format_name(ALSAMM_FORMAT)); #endif /* first check samplerate since channels numbers are samplerate dependent (double speed) */ /* set the stream rate */ rrate = alsamm_sr; #ifdef ALSAMM_DEBUG if(sys_verbose) post("Samplerate request: %i Hz",rrate); #endif dir=-1; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, &dir); if (err < 0) { check_error(err,"Rate not available"); return err; } if (rrate != alsamm_sr) { post("Warning: rate %iHz doesn't match requested %iHz", rrate,alsamm_sr); alsamm_sr = rrate; } else if(sys_verbose) post("Samplerate is set to %iHz",alsamm_sr); /* Info on channels */ { int maxchs,minchs,channels = *chs; if((err = snd_pcm_hw_params_get_channels_max(params, (unsigned int *)&maxchs)) < 0){ check_error(err,"Getting channels_max not available"); return err; } if((err = snd_pcm_hw_params_get_channels_min(params, (unsigned int *)&minchs)) < 0){ check_error(err,"Getting channels_min not available"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Getting channels:min=%d, max= %d for request=%d",minchs,maxchs,channels); #endif if(channels < 0)channels=maxchs; if(channels > maxchs)channels = maxchs; if(channels < minchs)channels = minchs; if(channels != *chs) post("requested channels=%d but used=%d",*chs,channels); *chs = channels; #ifdef ALSAMM_DEBUG if(sys_verbose) post("trying to use channels: %d",channels); #endif } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, *chs); if (err < 0) { check_error(err,"Channels count not available"); return err; } /* testing for channels */ if((err = snd_pcm_hw_params_get_channels(params,(unsigned int *)chs)) < 0) check_error(err,"Get channels not available"); #ifdef ALSAMM_DEBUG else if(sys_verbose) post("When setting channels count and got %d",*chs); #endif /* if buffersize is set use this instead buffertime */ if(alsamm_buffersize > 0){ #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: ask for max buffersize of %d samples", (unsigned int) alsamm_buffersize ); #endif alsamm_buffer_size = alsamm_buffersize; err = snd_pcm_hw_params_set_buffer_size_near(handle, params, (unsigned long *)&alsamm_buffer_size); if (err < 0) { check_error(err,"Unable to set max buffer size"); return err; } } else{ if(alsamm_buffertime <= 0) /* should never happen, but use 20ms */ alsamm_buffertime = 20000; #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: ask for max buffertime of %d ms", (unsigned int) (alsamm_buffertime*0.001) ); #endif err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &alsamm_buffertime, &dir); if (err < 0) { check_error(err,"Unable to set max buffer time"); return err; } } err = snd_pcm_hw_params_get_buffer_time(params, (unsigned int *)&alsamm_buffertime, &dir); if (err < 0) { check_error(err,"Unable to get buffer time"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: got buffertime to %f ms", (float) (alsamm_buffertime*0.001)); #endif err = snd_pcm_hw_params_get_buffer_size(params, (unsigned long *)&alsamm_buffer_size); if (err < 0) { check_error(err,"Unable to get buffer size"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: got buffersize to %d samples",(int) alsamm_buffer_size); #endif err = snd_pcm_hw_params_get_period_size(params, (unsigned long *)&alsamm_period_size, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Got period size of %d", (int) alsamm_period_size); #endif { unsigned int pmin,pmax; err = snd_pcm_hw_params_get_periods_min(params, &pmin, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } err = snd_pcm_hw_params_get_periods_min(params, &pmax, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } /* use maximum of periods */ if( alsamm_periods <= 0) alsamm_periods = pmax; alsamm_periods = (alsamm_periods > pmax)?pmax:alsamm_periods; alsamm_periods = (alsamm_periods < pmin)?pmin:alsamm_periods; err = snd_pcm_hw_params_set_periods(handle, params, alsamm_periods, dir); if (err > 0) { check_error(err,"Unable to set periods"); return err; } err = snd_pcm_hw_params_get_periods(params, &pmin, &dir); if (err > 0) { check_error(err,"Unable to get periods"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Got periods of %d, where periodsmin=%d, periodsmax=%d", alsamm_periods,pmin,pmax); #endif } /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { check_error(err,"Unable to set hw params"); return err; } #endif /* ALSAAPI9 */ return 0; }
int main( int argc, char *argv[] ) { struct structArgs cmdArgs; unsigned int val, val2; int dir; int errNum; cmdArgs.card = 0; // Default card. cmdArgs.control = 1; // Default control. // ************************************************************************ // ALSA control elements. // ************************************************************************ snd_pcm_t *pcmp; snd_pcm_hw_params_t *params; // snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; snd_pcm_uframes_t frames; // ************************************************************************ // Get command line parameters. // ************************************************************************ argp_parse( &argp, argc, argv, 0, 0, &cmdArgs ); printf( "Card = %i\n", cmdArgs.card ); printf( "Control = %i\n", cmdArgs.control ); sprintf( cmdArgs.deviceID, "hw:%i,%i", cmdArgs.card, cmdArgs.control ); printf( "Using device %s :", cmdArgs.deviceID ); /* Allocate a hardware parameters object. */ if ( snd_pcm_hw_params_alloca( ¶ms ) < 0 ) { fprintf( stderr, "Unable to allocate.\n" ); return -1; } /* Open PCM device for playback. */ // if ( snd_pcm_open( &pcmp, cmdArgs.deviceID, stream, 0 ) < 0 ) // { // fprintf( stderr, "Unable to open pcm device.\n" ); // return -1; // } /* Fill it in with default values. */ // if ( snd_pcm_hw_params_any( pcmp, params ) < 0 // { // fprintf( stderr, "Unable to set default values.\n" ); // return -1; // } /* Interleaved mode */ // snd_pcm_hw_params_set_access( pcmp, params, // SND_PCM_ACCESS_RW_INTERLEAVED ); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format( pcmp, params, SND_PCM_FORMAT_S16_LE ); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels( pcmp, params, 2 ); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near( pcmp, params, &val, &dir ); /* Write the parameters to the driver */ errNum = snd_pcm_hw_params( pcmp, params ); if ( errNum < 0 ) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror( errNum )); exit( 1 ); } /* Display information about the PCM interface */ printf( "PCM handle name = '%s'\n", snd_pcm_name( pcmp )); printf("PCM state = %s\n", snd_pcm_state_name( snd_pcm_state( pcmp ))); snd_pcm_hw_params_get_access( params, ( snd_pcm_access_t * ) &val ); printf( "access type = %s\n", snd_pcm_access_name(( snd_pcm_access_t ) val )); snd_pcm_hw_params_get_format( params, ( snd_pcm_format_t * ) &val ); printf( "format = '%s' (%s)\n", snd_pcm_format_name(( snd_pcm_format_t ) val ), snd_pcm_format_description(( snd_pcm_format_t ) val )); snd_pcm_hw_params_get_subformat( params, ( snd_pcm_subformat_t * ) &val ); printf( "subformat = '%s' (%s)\n", snd_pcm_subformat_name(( snd_pcm_subformat_t ) val ), snd_pcm_subformat_description(( snd_pcm_subformat_t ) val )); snd_pcm_hw_params_get_channels( params, &val ); printf( "channels = %d\n", val ); snd_pcm_hw_params_get_rate( params, &val, &dir ); printf( "rate = %d bps\n", val ); snd_pcm_hw_params_get_period_time( params, &val, &dir ); printf( "period time = %d us\n", val ); snd_pcm_hw_params_get_period_size( params, &frames, &dir ); printf( "period size = %d frames\n", ( int ) frames ); snd_pcm_hw_params_get_buffer_time( params, &val, &dir ); printf( "buffer time = %d us\n", val ); snd_pcm_hw_params_get_buffer_size( params, ( snd_pcm_uframes_t * ) &val ); printf( "buffer size = %d frames\n", val ); snd_pcm_hw_params_get_periods( params, &val, &dir ); printf( "periods per buffer = %d frames\n", val ); snd_pcm_hw_params_get_rate_numden( params, &val, &val2 ); printf( "exact rate = %d/%d bps\n", val, val2 ); val = snd_pcm_hw_params_get_sbits( params ); printf( "significant bits = %d\n", val ); // snd_pcm_hw_params_get_tick_time( params, &val, &dir ); // printf( "tick time = %d us\n", val ); val = snd_pcm_hw_params_is_batch( params ); printf( "is batch = %d\n", val ); val = snd_pcm_hw_params_is_block_transfer( params ); printf( "is block transfer = %d\n", val ); val = snd_pcm_hw_params_is_double( params ); printf( "is double = %d\n", val ); val = snd_pcm_hw_params_is_half_duplex( params ); printf( "is half duplex = %d\n", val ); val = snd_pcm_hw_params_is_joint_duplex( params ); printf( "is joint duplex = %d\n", val ); val = snd_pcm_hw_params_can_overrange( params ); printf( "can overrange = %d\n", val ); val = snd_pcm_hw_params_can_mmap_sample_resolution( params ); printf( "can mmap = %d\n", val ); val = snd_pcm_hw_params_can_pause( params ); printf( "can pause = %d\n", val ); val = snd_pcm_hw_params_can_resume( params ); printf( "can resume = %d\n", val ); val = snd_pcm_hw_params_can_sync_start( params ); printf( "can sync start = %d\n", val ); snd_pcm_close( pcmp ); return 0; }
static int set_params(AudioDevice *ad, AudioFormat *format_p, int *ch_p, unsigned int *rate_p) { ALSA_data *alsa = (ALSA_data *)ad->private_data; int r, err; snd_pcm_format_t f; AudioFormat format = *format_p; snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; int ch = *ch_p; unsigned int rate = *rate_p; unsigned int buffer, period; snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); ad->format = _AUDIO_FORMAT_UNSET; *format_p = _AUDIO_FORMAT_UNSET; *ch_p = 0; *rate_p = 0; /* format part */ switch (format) { case _AUDIO_FORMAT_MU_LAW: f = SND_PCM_FORMAT_MU_LAW; break; case _AUDIO_FORMAT_A_LAW: f = SND_PCM_FORMAT_A_LAW; break; case _AUDIO_FORMAT_ADPCM: f = SND_PCM_FORMAT_IMA_ADPCM; break; case _AUDIO_FORMAT_U8: f = SND_PCM_FORMAT_U8; break; case _AUDIO_FORMAT_S8: f = SND_PCM_FORMAT_S8; break; case _AUDIO_FORMAT_U16_LE: f = SND_PCM_FORMAT_U16_LE; break; case _AUDIO_FORMAT_U16_BE: f = SND_PCM_FORMAT_U16_BE; break; case _AUDIO_FORMAT_S16_LE: f = SND_PCM_FORMAT_S16_LE; break; case _AUDIO_FORMAT_S16_BE: f = SND_PCM_FORMAT_S16_BE; break; #if 0 case _AUDIO_FORMAT_S32_LE: f = SND_PCM_FORMAT_U32_LE; break; case _AUDIO_FORMAT_S32_BE: f = SND_PCM_FORMAT_S32_BE; break; #endif default: show_message_fnc("format %d is invalid.\n", format); return 0; } if ((err = snd_pcm_hw_params_any(alsa->fd, hwparams)) < 0) { show_message_fnc("snd_pcm_hw_params_any() failed.\n"); return 0; } if ((err = snd_pcm_hw_params_set_access(alsa->fd, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { show_message_fnc("snd_pcm_hw_params_set_access() failed.\n"); return 0; } if ((err = snd_pcm_hw_params_set_format(alsa->fd, hwparams, f)) < 0) { show_message_fnc("snd_pcm_hw_params_set_format() failed.\n"); return 0; } ad->format = format; *format_p = format; /* channel part */ if ((err = snd_pcm_hw_params_set_channels(alsa->fd, hwparams, ch)) < 0) { show_message_fnc("snd_pcm_hw_params_set_channels() failed.\n"); return 0; } *ch_p = ch; /* rate part */ if ((err = snd_pcm_hw_params_set_rate_near(alsa->fd, hwparams, &rate, 0)) < 0) { show_message_fnc("snd_pcm_hw_params_set_rate_near() failed.\n"); return 0; } *rate_p = rate; /* buffer & period */ buffer = 500000; period = 500000 / 4; if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa->fd, hwparams, &buffer, 0)) < 0) { show_message_fnc("snd_pcm_hw_params_set_buffer_near() failed.\n"); return 0; } r = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa->buffer_size); if ((err = snd_pcm_hw_params_set_period_time_near(alsa->fd, hwparams, &period, 0)) < 0) { show_message_fnc("snd_pcm_hw_params_set_period_near() failed.\n"); return 0; } r = snd_pcm_hw_params_get_period_size(hwparams, &alsa->period_size, 0); if ((err = snd_pcm_hw_params(alsa->fd, hwparams)) < 0) { perror("snd_pcm_hw_params"); err_message_fnc("snd_pcm_hw_params() failed.\n"); snd_pcm_hw_params_dump(hwparams, alsa->log); return 0; } r = snd_pcm_hw_params_get_channels(hwparams, &ad->channels); r = snd_pcm_hw_params_get_rate(hwparams, &ad->speed, 0); r = r; // dummy #ifdef DEBUG { snd_pcm_format_t form; debug_message_fnc("format "); r = snd_pcm_hw_params_get_format(hwparams, &form); switch (form) { case SND_PCM_FORMAT_MU_LAW: debug_message("MU_LAW "); break; case SND_PCM_FORMAT_A_LAW: debug_message("A_LAW "); break; case SND_PCM_FORMAT_IMA_ADPCM: debug_message("ADPCM "); break; case SND_PCM_FORMAT_U8: debug_message("U8 "); break; case SND_PCM_FORMAT_S8: debug_message("S8 "); break; case SND_PCM_FORMAT_U16_LE: debug_message("U16LE "); break; case SND_PCM_FORMAT_U16_BE: debug_message("U16BE "); break; case SND_PCM_FORMAT_S16_LE: debug_message("S16LE "); break; case SND_PCM_FORMAT_S16_BE: debug_message("S16BE "); break; #if 0 case SND_PCM_FORMAT_U32_LE: debug_message("U32LE "); break; case SND_PCM_FORMAT_S32_BE: debug_message("S32BE "); break; #endif default: debug_message("UNKNOWN "); break; } debug_message("%d ch %d Hz buffer %ld period %ld OK\n", ad->channels, ad->speed, alsa->buffer_size, alsa->period_size); } #endif /* sw_params */ if ((err = snd_pcm_sw_params_current(alsa->fd, swparams)) < 0) { show_message_fnc("snd_pcm_sw_params_any() failed.\n"); return 0; } if ((err = snd_pcm_sw_params(alsa->fd, swparams)) < 0) { show_message_fnc("snd_pcm_sw_params() failed.\n"); return 0; } debug_message_fnc("1 sample -> %ld bytes\n", snd_pcm_samples_to_bytes(alsa->fd, 1)); return 1; }
/************************************************************************** * ALSA_TraceParameters [internal] * * used to trace format changes, hw and sw parameters */ void ALSA_TraceParameters(snd_pcm_hw_params_t * hw_params, snd_pcm_sw_params_t * sw, int full) { int err; snd_pcm_format_t format; snd_pcm_access_t access; #define X(x) ((x)? "true" : "false") if (full) TRACE("FLAGS: sampleres=%s overrng=%s pause=%s resume=%s syncstart=%s batch=%s block=%s double=%s " "halfd=%s joint=%s\n", X(snd_pcm_hw_params_can_mmap_sample_resolution(hw_params)), X(snd_pcm_hw_params_can_overrange(hw_params)), X(snd_pcm_hw_params_can_pause(hw_params)), X(snd_pcm_hw_params_can_resume(hw_params)), X(snd_pcm_hw_params_can_sync_start(hw_params)), X(snd_pcm_hw_params_is_batch(hw_params)), X(snd_pcm_hw_params_is_block_transfer(hw_params)), X(snd_pcm_hw_params_is_double(hw_params)), X(snd_pcm_hw_params_is_half_duplex(hw_params)), X(snd_pcm_hw_params_is_joint_duplex(hw_params))); #undef X err = snd_pcm_hw_params_get_access(hw_params, &access); if (err >= 0) { TRACE("access=%s\n", snd_pcm_access_name(access)); } else { snd_pcm_access_mask_t * acmask; acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof()); snd_pcm_hw_params_get_access_mask(hw_params, acmask); for ( access = SND_PCM_ACCESS_MMAP_INTERLEAVED; access <= SND_PCM_ACCESS_LAST; access++) if (snd_pcm_access_mask_test(acmask, access)) TRACE("access=%s\n", snd_pcm_access_name(access)); HeapFree( GetProcessHeap(), 0, acmask ); } err = snd_pcm_hw_params_get_format(hw_params, &format); if (err >= 0) { TRACE("format=%s\n", snd_pcm_format_name(format)); } else { snd_pcm_format_mask_t * fmask; fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof()); snd_pcm_hw_params_get_format_mask(hw_params, fmask); for ( format = SND_PCM_FORMAT_S8; format <= SND_PCM_FORMAT_LAST ; format++) if ( snd_pcm_format_mask_test(fmask, format) ) TRACE("format=%s\n", snd_pcm_format_name(format)); HeapFree( GetProcessHeap(), 0, fmask ); } do { int err=0; unsigned int val=0; err = snd_pcm_hw_params_get_channels(hw_params, &val); if (err<0) { unsigned int min = 0; unsigned int max = 0; err = snd_pcm_hw_params_get_channels_min(hw_params, &min), err = snd_pcm_hw_params_get_channels_max(hw_params, &max); TRACE("channels_min=%u, channels_min_max=%u\n", min, max); } else { TRACE("channels=%d\n", val); } } while(0); do { int err=0; snd_pcm_uframes_t val=0; err = snd_pcm_hw_params_get_buffer_size(hw_params, &val); if (err<0) { snd_pcm_uframes_t min = 0; snd_pcm_uframes_t max = 0; err = snd_pcm_hw_params_get_buffer_size_min(hw_params, &min), err = snd_pcm_hw_params_get_buffer_size_max(hw_params, &max); TRACE("buffer_size_min=%lu, buffer_size_min_max=%lu\n", min, max); } else { TRACE("buffer_size=%lu\n", val); } } while(0); #define X(x) do { \ int err=0; \ int dir=0; \ unsigned int val=0; \ err = snd_pcm_hw_params_get_##x(hw_params,&val, &dir); \ if (err<0) { \ unsigned int min = 0; \ unsigned int max = 0; \ err = snd_pcm_hw_params_get_##x##_min(hw_params, &min, &dir); \ err = snd_pcm_hw_params_get_##x##_max(hw_params, &max, &dir); \ TRACE(#x "_min=%u " #x "_max=%u\n", min, max); \ } else \ TRACE(#x "=%d\n", val); \ } while(0) X(rate); X(buffer_time); X(periods); do { int err=0; int dir=0; snd_pcm_uframes_t val=0; err = snd_pcm_hw_params_get_period_size(hw_params, &val, &dir); if (err<0) { snd_pcm_uframes_t min = 0; snd_pcm_uframes_t max = 0; err = snd_pcm_hw_params_get_period_size_min(hw_params, &min, &dir), err = snd_pcm_hw_params_get_period_size_max(hw_params, &max, &dir); TRACE("period_size_min=%lu, period_size_min_max=%lu\n", min, max); } else { TRACE("period_size=%lu\n", val); } } while(0); X(period_time); #undef X if (!sw) return; }
static int bluetooth_a2dp_init(struct bluetooth_data *data, snd_pcm_hw_params_t *params) { struct bluetooth_alsa_config *cfg = &data->alsa_config; sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities; unsigned int max_bitpool, min_bitpool, rate, channels; int dir; snd_pcm_hw_params_get_rate(params, &rate, &dir); snd_pcm_hw_params_get_channels(params, &channels); switch (rate) { case 48000: cap->frequency = BT_SBC_SAMPLING_FREQ_48000; break; case 44100: cap->frequency = BT_SBC_SAMPLING_FREQ_44100; break; case 32000: cap->frequency = BT_SBC_SAMPLING_FREQ_32000; break; case 16000: cap->frequency = BT_SBC_SAMPLING_FREQ_16000; break; default: DBG("Rate %d not supported", rate); return -1; } if (cfg->has_channel_mode) cap->channel_mode = cfg->channel_mode; else if (channels == 2) { if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; } else { if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; } if (!cap->channel_mode) { DBG("No supported channel modes"); return -1; } if (cfg->has_block_length) cap->block_length = cfg->block_length; else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) cap->block_length = BT_A2DP_BLOCK_LENGTH_16; else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) cap->block_length = BT_A2DP_BLOCK_LENGTH_12; else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) cap->block_length = BT_A2DP_BLOCK_LENGTH_8; else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) cap->block_length = BT_A2DP_BLOCK_LENGTH_4; else { DBG("No supported block lengths"); return -1; } if (cfg->has_subbands) cap->subbands = cfg->subbands; if (cap->subbands & BT_A2DP_SUBBANDS_8) cap->subbands = BT_A2DP_SUBBANDS_8; else if (cap->subbands & BT_A2DP_SUBBANDS_4) cap->subbands = BT_A2DP_SUBBANDS_4; else { DBG("No supported subbands"); return -1; } if (cfg->has_allocation_method) cap->allocation_method = cfg->allocation_method; if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) cap->allocation_method = BT_A2DP_ALLOCATION_SNR; if (cfg->has_bitpool) min_bitpool = max_bitpool = cfg->bitpool; else { min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool); max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool); } cap->min_bitpool = min_bitpool; cap->max_bitpool = max_bitpool; return 0; }
int main() { long loops; int rc,i = 0; int size; FILE *fp ; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val,val2; int dir; snd_pcm_uframes_t frames; char *buffer; if( (fp =fopen("sound.wav","w")) < 0) printf("open sound.wav fial\n"); /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s/n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_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 */ printf("size = %d\n",size); buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 10000000 / val; while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, frames); printf("%d\n",i++); 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 = fwrite( buffer,1, size,fp); rc = write(1,buffer,size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes/n", rc); else printf("fwrite buffer success\n"); } /******************打印参数*********************/ snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); //snd_pcm_hw_params_get_tick_time(params, &val, &dir); printf("tick time = %d us\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); /*******************************************************************/ snd_pcm_drain(handle); snd_pcm_close(handle); fclose(fp); free(buffer); return 0; }
int main() { int result; snd_pcm_t *handle = NULL; snd_pcm_hw_params_t *params = NULL; snd_pcm_uframes_t frames; snd_pcm_access_t access; snd_pcm_format_t format; unsigned int rate = 44100; unsigned int val, val2; int dir = 0; const char *device = getenv ("ALSA_DEFAULT"); if (device == NULL) { device = "default"; } result = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0); if (result < 0) showErrorAndExit(result, "Error: Unable to open PCM device: %s\n"); result = snd_pcm_hw_params_malloc(¶ms); if (result < 0) showErrorAndExit(result, "Error: No memory for hardware parameters: %s\n"); result = snd_pcm_hw_params_any(handle, params); if (result < 0) showErrorAndExit(result, "Error: Cannot read HW params: %s\n"); result = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (result < 0) showErrorAndExit(result, "Could not set access method: %s\n"); result = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); if (result < 0) showErrorAndExit(result, "Error: Could not set output format: %s\n"); result = snd_pcm_hw_params_set_channels(handle, params, 1); if (result < 0) showErrorAndExit(result, "Error: Cannot set to 1 channel: %s\n"); result = snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); if (result < 0) showErrorAndExit(result, "Error: Could not set rate: %s\n"); result = snd_pcm_hw_params(handle, params); if (result < 0) showErrorAndExit(result, "Error: Could not write HW params: %s\n"); printf("Card Parameters\n"); printf("%30s: %s\n", "Alsa Library Version", snd_asoundlib_version()); result = snd_pcm_hw_params_get_access(params, &access); if (result < 0) { showErrorAndExit(result, "Error: Could not retrieve access mode: %s\n"); } else { printf("%30s: %s\n", "Access Method", snd_pcm_access_name(access)); } result = snd_pcm_hw_params_get_format(params, &format); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve format type: %d\n"); } else { printf("%30s: %s\n", "Format", snd_pcm_format_name(format)); } result = snd_pcm_hw_params_get_channels(params, &val); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve channel count: %s\n"); } else { printf("%30s: %d\n", "Channels", val); } result = snd_pcm_hw_params_get_rate(params, &val, &dir); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve rate: %s\n"); } else { printf("%30s: %d bps\n", "Rate", val); } result = snd_pcm_hw_params_get_period_time(params, &val, &dir); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve period time: %s\n"); } else { printf("%30s: %d us\n", "Period Time", val); } result = snd_pcm_hw_params_get_period_size(params, &frames, &dir); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve period size: %s\n"); } else { printf("%30s: %d frames\n", "Period Size", (int) frames); } result = snd_pcm_hw_params_get_buffer_time(params, &val, &dir); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve buffer time: %s\n"); } else { printf("%30s: %d us\n", "Buffer Time", val); } result = snd_pcm_hw_params_get_buffer_size(params, &frames); if (result < 0) { showErrorAndExit(result, "Error: Unable to retrieve buffer size: %s\n"); } else { printf("%30s: %d frames\n", "Buffer Size", (int) frames); } result = snd_pcm_hw_params_get_periods(params, &val, &dir); if (result < 0) { showErrorAndExit(result, "Error: Unable to get buffer periods: %s\n"); } else { printf("%30s: %d frames\n", "Periods per Buffer", val); } result = snd_pcm_hw_params_get_rate_numden(params, &val, &val2); if (result < 0) { showErrorAndExit(result, "Error: Unable to get rate numerator/denominator: %s\n"); } else { printf("%30s: %d/%d bps\n", "Exact Rate", val, val2); } val = snd_pcm_hw_params_get_sbits(params); printf("%30s: %d\n", "Significant Bits", val); result = snd_pcm_hw_params_get_tick_time(params, &val, &dir); if (result < 0) { showErrorAndExit(result, "Error: Could not retrieve tick time: %s\n"); } else { printf("%30s: %d\n", "Tick Time", val); } printf("Card Capabilities\n"); val = snd_pcm_hw_params_is_batch(params); printf("%30s: %s\n", "Batch Transfer", (val ? "Yes" : "No")); val = snd_pcm_hw_params_is_block_transfer(params); printf("%30s: %s\n", "Block Transfer", (val ? "Yes" : "No")); val = snd_pcm_hw_params_is_double(params); printf("%30s: %s\n", "Double Buffering", (val ? "Yes" : "No")); val = snd_pcm_hw_params_is_half_duplex(params); printf("%30s: %s\n", "Half Duplex Only", (val ? "Yes" : "No")); val = snd_pcm_hw_params_is_joint_duplex(params); printf("%30s: %s\n", "Joint Duplex Capable", (val ? "Yes" : "No")); val = snd_pcm_hw_params_can_overrange(params); printf("%30s: %s\n", "Support Overrange Detection", (val ? "Yes" : "No")); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("%30s: %s\n", "Support Sample-res Mmap", (val ? "Yes" : "No")); val = snd_pcm_hw_params_can_pause(params); printf("%30s: %s\n", "Can Pause", (val ? "Yes" : "No")); val = snd_pcm_hw_params_can_resume(params); printf("%30s: %s\n", "Can Resume", (val ? "Yes" : "No")); val = snd_pcm_hw_params_can_sync_start(params); printf("%30s: %s\n", "Support Sync Start", (val ? "Yes" : "No")); result = snd_pcm_close(handle); if (result < 0) showErrorAndExit(result, "Error: Could not close PCM device: %s\n"); return 0; }
int open_alsa_read(struct pcm **p, char *name) { snd_pcm_t *pcm; if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", name); return 0; } snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); if (snd_pcm_hw_params_any(pcm, params) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE) < 0) { fprintf(stderr, "Error setting S16_LE format.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_rate_resample(pcm, params, 0) < 0) { fprintf(stderr, "Error disabling resampling.\n"); snd_pcm_close(pcm); return 0; } unsigned rate_min = 8000; int dir_min = 0; if (snd_pcm_hw_params_set_rate_min(pcm, params, &rate_min, &dir_min) < 0 || rate_min < 8000) { fprintf(stderr, "Error setting min rate.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params(pcm, params) < 0) { fprintf(stderr, "Error setting HW params.\n"); snd_pcm_close(pcm); return 0; } unsigned int rate = 0; if (snd_pcm_hw_params_get_rate(params, &rate, 0) < 0) { fprintf(stderr, "Error getting rate.\n"); snd_pcm_close(pcm); return 0; } unsigned int channels = 0; if (snd_pcm_hw_params_get_channels(params, &channels) < 0) { fprintf(stderr, "Error getting channels.\n"); snd_pcm_close(pcm); return 0; } struct alsa *alsa = (struct alsa *)malloc(sizeof(struct alsa)); alsa->base.close = close_alsa; alsa->base.info = info_alsa; alsa->base.rate = rate_alsa; alsa->base.channels = channels_alsa; alsa->base.rw = read_alsa; alsa->base.data = (void *)alsa; alsa->pcm = pcm; alsa->r = rate; alsa->c = channels; alsa->frames = 0; *p = &(alsa->base); return 1; }
/** * Allocate the memory-mapped buffer for direct sound, and set up the * callback. */ static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi) { snd_pcm_t *pcm = pdbi->pcm; snd_pcm_format_t format; snd_pcm_uframes_t frames, ofs, avail, psize, boundary; unsigned int channels, bits_per_sample, bits_per_frame; int err, mmap_mode; const snd_pcm_channel_area_t *areas; snd_pcm_hw_params_t *hw_params = pdbi->hw_params; snd_pcm_sw_params_t *sw_params = pdbi->sw_params; void *buf; mmap_mode = snd_pcm_type(pcm); if (mmap_mode == SND_PCM_TYPE_HW) TRACE("mmap'd buffer is a direct hardware buffer.\n"); else if (mmap_mode == SND_PCM_TYPE_DMIX) TRACE("mmap'd buffer is an ALSA dmix buffer\n"); else TRACE("mmap'd buffer is an ALSA type %d buffer\n", mmap_mode); err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); err = snd_pcm_hw_params_get_format(hw_params, &format); err = snd_pcm_hw_params_get_buffer_size(hw_params, &frames); err = snd_pcm_hw_params_get_channels(hw_params, &channels); bits_per_sample = snd_pcm_format_physical_width(format); bits_per_frame = bits_per_sample * channels; if (TRACE_ON(dsalsa)) ALSA_TraceParameters(hw_params, NULL, FALSE); TRACE("format=%s frames=%ld channels=%d bits_per_sample=%d bits_per_frame=%d\n", snd_pcm_format_name(format), frames, channels, bits_per_sample, bits_per_frame); pdbi->mmap_buflen_frames = frames; pdbi->mmap_buflen_bytes = snd_pcm_frames_to_bytes( pcm, frames ); snd_pcm_sw_params_current(pcm, sw_params); snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 0); snd_pcm_sw_params_get_boundary(sw_params, &boundary); snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, boundary); snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, boundary); snd_pcm_sw_params_set_silence_size(pcm, sw_params, 0); snd_pcm_sw_params_set_avail_min(pcm, sw_params, 0); err = snd_pcm_sw_params(pcm, sw_params); avail = snd_pcm_avail_update(pcm); if ((snd_pcm_sframes_t)avail < 0) { ERR("No buffer is available: %s.\n", snd_strerror(avail)); return DSERR_GENERIC; } if (!pdbi->mmap) { buf = pdbi->mmap_buffer = HeapAlloc(GetProcessHeap(), 0, pdbi->mmap_buflen_bytes); if (!buf) return DSERR_OUTOFMEMORY; snd_pcm_format_set_silence(format, buf, pdbi->mmap_buflen_frames); pdbi->mmap_pos = 0; } else { err = snd_pcm_mmap_begin(pcm, &areas, &ofs, &avail); if ( err < 0 ) { ERR("Can't map sound device for direct access: %s/%d\n", snd_strerror(err), err); return DSERR_GENERIC; } snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames); pdbi->mmap_pos = ofs + snd_pcm_mmap_commit(pcm, ofs, 0); pdbi->mmap_buffer = areas->addr; } TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n", frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer); return DS_OK; }
int sndout_alsa_start(int rate_, int stereo) { snd_pcm_hw_params_t *hwparams = NULL; unsigned int rate = rate_; int samples, shift; int ret; samples = rate * 40 / 1000; for (shift = 8; (1 << shift) < samples; shift++) ; period_size = 1 << shift; buffer_size = 8 * period_size; snd_pcm_hw_params_alloca(&hwparams); ret = snd_pcm_hw_params_any(handle, hwparams); ret |= snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); ret |= snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE); ret |= snd_pcm_hw_params_set_channels(handle, hwparams, stereo ? 2 : 1); ret |= snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0); ret |= snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); ret |= snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, NULL); if (ret != 0) { fprintf(stderr, PFX "failed to set hwparams\n"); goto fail; } ret = snd_pcm_hw_params(handle, hwparams); if (ret != 0) { fprintf(stderr, PFX "failed to apply hwparams: %d\n", ret); goto fail; } snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size); snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL); snd_pcm_hw_params_get_channels(hwparams, &channels); silent_period = realloc(silent_period, period_size * 2 * channels); if (silent_period != NULL) memset(silent_period, 0, period_size * 2 * channels); ret = snd_pcm_prepare(handle); if (ret != 0) { fprintf(stderr, PFX "snd_pcm_prepare failed: %d\n", ret); goto fail; } ret = snd_pcm_start(handle); if (ret != 0) { fprintf(stderr, PFX "snd_pcm_start failed: %d\n", ret); goto fail; } failure_counter = 0; return 0; fail: // to flush out redirected logs fflush(stdout); fflush(stderr); return -1; }
bool QAudioInputPrivate::open( QObject *input ) { // Open the Alsa capture device. bool rc = true; int err; unsigned int freakuency = frequency; if ((err = snd_pcm_open(&handle, m_device.constData(), //"plughw:0,0" SND_PCM_STREAM_CAPTURE, 0/*SND_PCM_ASYNC*/)) < 0) { qWarning( "QAudioInput: snd_pcm_open: error %d", err); rc = false; } else { snd_pcm_hw_params_t *hwparams; // We want non-blocking mode. snd_pcm_nonblock(handle, 1); // Set the desired parameters. snd_pcm_hw_params_alloca(&hwparams); err = snd_pcm_hw_params_any(handle, hwparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_any: err %d", err); } err = snd_pcm_hw_params_set_access(handle, hwparams, access); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_access: err %d",err); } err = snd_pcm_hw_params_set_format(handle, hwparams,format); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_format: err %d",err); } err = snd_pcm_hw_params_set_channels(handle,hwparams,(unsigned int)channels); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_channels: err %d",err); } err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err); } if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) { qWarning("QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency); } if ( samplesPerBlock != -1 ) { // Set buffer and period sizes based on the supplied block size. sample_size = (snd_pcm_uframes_t)( samplesPerBlock * channels / 8 ); err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err); } if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) { qWarning( "QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency); } err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } period_time = 1000000 * 256 / frequency; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err); } } else { // Use the largest buffer and period sizes we can. err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } period_time = 1000000 * 256 / frequency; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err); } } err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_hw_params: err %d",err); } int dir; unsigned int vval, vval2; snd_pcm_access_t aval; snd_pcm_format_t fval; snd_pcm_subformat_t sval; qLog(QAudioInput) << "PCM handle name = " << snd_pcm_name(handle); qLog(QAudioInput) << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle)); snd_pcm_hw_params_get_access(hwparams,&aval); vval = (unsigned int)aval; if ( (int)vval != (int)access ) { qLog(QAudioInput) << QString("access type not set, want %1 got %2") .arg(snd_pcm_access_name((snd_pcm_access_t)access)) .arg(snd_pcm_access_name((snd_pcm_access_t)vval)); access = (snd_pcm_access_t)vval; } qLog(QAudioInput) << "access type = " << snd_pcm_access_name((snd_pcm_access_t)vval); snd_pcm_hw_params_get_format(hwparams, &fval); vval = (unsigned int)fval; if ( (int)vval != (int)format ) { qLog(QAudioInput) << QString("format type not set, want %1 got %2") .arg(snd_pcm_format_name((snd_pcm_format_t)format)) .arg(snd_pcm_format_name((snd_pcm_format_t)vval)); format = (snd_pcm_format_t)vval; } qLog(QAudioInput) << QString("format = '%1' (%2)") .arg(snd_pcm_format_name((snd_pcm_format_t)vval)) .arg(snd_pcm_format_description((snd_pcm_format_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_subformat(hwparams,&sval); vval = (unsigned int)sval; qLog(QAudioInput) << QString("subformat = '%1' (%2)") .arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval)) .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_channels(hwparams, &vval); if ( (int)vval != (int)channels ) { qLog(QAudioInput) << QString("channels type not set, want %1 got %2").arg(channels).arg(vval); channels = vval; } qLog(QAudioInput) << "channels = " << vval; snd_pcm_hw_params_get_rate(hwparams, &vval, &dir); if ( (int)vval != (int)frequency ) { qLog(QAudioInput) << QString("frequency type not set, want %1 got %2").arg(frequency).arg(vval); frequency = vval; } qLog(QAudioInput) << "rate =" << vval << " bps"; snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); qLog(QAudioInput) << "period time =" << period_time << " us"; snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir); qLog(QAudioInput) << "period size =" << (int)period_size; snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); qLog(QAudioInput) << "buffer time =" << buffer_time; snd_pcm_hw_params_get_buffer_size(hwparams,(snd_pcm_uframes_t *) &buffer_size); qLog(QAudioInput) << "buffer size =" << (int)buffer_size; snd_pcm_hw_params_get_periods(hwparams, &vval, &dir); qLog(QAudioInput) << "periods per buffer =" << vval; snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2); qLog(QAudioInput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData(); vval = snd_pcm_hw_params_get_sbits(hwparams); qLog(QAudioInput) << "significant bits =" << vval; snd_pcm_hw_params_get_tick_time(hwparams,&vval, &dir); qLog(QAudioInput) << "tick time =" << vval; vval = snd_pcm_hw_params_is_batch(hwparams); qLog(QAudioInput) << "is batch =" << vval; vval = snd_pcm_hw_params_is_block_transfer(hwparams); qLog(QAudioInput) << "is block transfer =" << vval; vval = snd_pcm_hw_params_is_double(hwparams); qLog(QAudioInput) << "is double =" << vval; vval = snd_pcm_hw_params_is_half_duplex(hwparams); qLog(QAudioInput) << "is half duplex =" << vval; vval = snd_pcm_hw_params_is_joint_duplex(hwparams); qLog(QAudioInput) << "is joint duplex =" << vval; vval = snd_pcm_hw_params_can_overrange(hwparams); qLog(QAudioInput) << "can overrange =" << vval; vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams); qLog(QAudioInput) << "can mmap =" << vval; vval = snd_pcm_hw_params_can_pause(hwparams); qLog(QAudioInput) << "can pause =" << vval; vval = snd_pcm_hw_params_can_resume(hwparams); qLog(QAudioInput) << "can resume =" << vval; vval = snd_pcm_hw_params_can_sync_start(hwparams); qLog(QAudioInput) << "can sync start =" << vval; snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_sw_params_current(handle, swparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_current: err %d",err); } err = snd_pcm_sw_params_set_start_threshold(handle,swparams,period_size); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_start_threshold: err %d",err); } err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_avail_min: err %d",err); } err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params_set_xfer_align: err %d",err); } err = snd_pcm_sw_params(handle, swparams); if ( err < 0 ) { qWarning( "QAudioInput: snd_pcm_sw_params: err %d",err); } snd_pcm_prepare(handle); snd_pcm_start(handle); int count = snd_pcm_poll_descriptors_count(handle); pollfd *pfds = new pollfd[count]; snd_pcm_poll_descriptors(handle, pfds, count); for (int i = 0; i < count; ++i) { if ((pfds[i].events & POLLIN) != 0) { notifier = new QSocketNotifier(pfds[i].fd, QSocketNotifier::Read); QObject::connect(notifier, SIGNAL(activated(int)), input, SIGNAL(readyRead())); break; } } if (notifier == NULL) { rc = false; } delete pfds; } return rc; }
int initAlsa(char **argv,int optind) { snd_pcm_hw_params_t *hw_params; int err,n; unsigned int Fs; if ((err = snd_pcm_open(&capture_handle, argv[optind], SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf(stderr, "Alsa cannot open audio device %s (%s)\n",argv[optind], snd_strerror(err)); return 1; } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf(stderr, "Alsa cannot allocate hardware parameter structure (%s)\n",snd_strerror(err)); return 1; } if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { fprintf(stderr, "Alsa cannot initialize hardware parameter structure (%s)\n",snd_strerror(err)); return 1; } if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params,SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "Alsa cannot set access type (%s)\n",snd_strerror(err)); return 1; } if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params,SND_PCM_FORMAT_S16)) < 0) { fprintf(stderr, "Alsa cannot set sample format (%s)\n",snd_strerror(err)); return 1; } snd_pcm_hw_params_set_rate_resample(capture_handle, hw_params,0); Fs=19200; n=1; if ((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &Fs,&n)) < 0) { fprintf(stderr, "Alsa cannot set sample rate (%s)\n",snd_strerror(err)); return 1; } fprintf(stderr, "Alsa sample rate %d\n",Fs); if(snd_pcm_hw_params_get_channels (hw_params, &nbch)!=0) { fprintf(stderr, "Alsa cannot get number of channels\n"); return 1; } if(nbch>4) { fprintf(stderr, "Alsa too much channels\n"); return 1; } if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) { fprintf(stderr, "Alsa cannot set parameters (%s)\n",snd_strerror(err)); return 1; } snd_pcm_hw_params_free(hw_params); if ((err = snd_pcm_prepare(capture_handle)) < 0) { fprintf(stderr, "Alsa cannot prepare audio interface for use (%s)\n",snd_strerror(err)); return 1; } for(n=0; n<nbch; n++) { channel[n].chn=n; channel[n].Infs=Fs; channel[n].InBuff=malloc(MAXNBFRAMES*sizeof(sample_t)); } for(; n<MAXNBCHANNELS; n++) channel[n].Infs=0; return (0); }
pcm_player *pcm_player_init(int framerate, int nchannels, int sampwidth) { pcm_player *player; int retval, format, buffsz; char *buff, *devname; snd_pcm_t *pcm_handle; snd_pcm_stream_t stream; snd_pcm_hw_params_t *hwparams; snd_pcm_uframes_t periodsize; // check parameters if(nchannels != 1 && nchannels != 2) { fprintf(stderr, "error: unsupported channels: %d\n", nchannels); return NULL; } if(sampwidth == 1) format = SND_PCM_FORMAT_U8; else if(sampwidth == 2) format = SND_PCM_FORMAT_S16_LE; else if(sampwidth == 3) format = SND_PCM_FORMAT_S24_LE; else if(sampwidth == 4) format = SND_PCM_FORMAT_S32_LE; else { fprintf(stderr, "error: unsupported sample width: %d\n", sampwidth); return NULL; } // allocate the structure player = (pcm_player*)malloc(sizeof(pcm_player)); if(player == NULL) return NULL; // open the PCM device in playback mode devname = "default"; stream = SND_PCM_STREAM_PLAYBACK; if((retval = snd_pcm_open(&pcm_handle, devname, stream, 0)) < 0) { fprintf(stderr, "error: can't PCM device: %s\n", snd_strerror(retval)); free(player); return NULL; } // allocate parameters object and fill it with default values snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_any(pcm_handle, hwparams); // set parameters if((retval = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "error: can't set interleaved mode: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } if ((retval = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format)) < 0) { fprintf(stderr, "error: can't set format: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } if ((retval = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, nchannels)) < 0) { fprintf(stderr, "error: can't set channels: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } if ((retval = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &framerate, 0)) < 0) { fprintf(stderr, "error: can't set rate: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } periodsize = framerate / 10; if((retval = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, periodsize, 0)) < 0) { fprintf(stderr, "error: can't set period size: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } // write parameters if ((retval = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { fprintf(stderr, "error: can't set hardware parameters: %s\n", snd_strerror(retval)); snd_pcm_close(pcm_handle); free(player); return NULL; } // resume information printf("PCM name: %s\n", snd_pcm_name(pcm_handle)); snd_pcm_hw_params_get_channels(hwparams, &nchannels); printf("channels: %i ", nchannels); if (nchannels == 1) printf("(mono)\n"); else if (nchannels == 2) printf("(stereo)\n"); snd_pcm_hw_params_get_rate(hwparams, &framerate, 0); printf("framerate: %d Hz\n", framerate); // allocate buffer to hold single period snd_pcm_hw_params_get_period_size(hwparams, &periodsize, 0); printf("period size: %d\n", periodsize); buffsz = sampwidth * nchannels * periodsize; printf("buffer size: %d\n", buffsz); buff = (char*)malloc(buffsz); if(buff == NULL) { fprintf(stderr, "error: can't allocate pcm buffer\n"); snd_pcm_close(pcm_handle); free(player); return NULL; } // set player attributes player->pcm_handle = pcm_handle; player->framerate = framerate; player->nchannels = nchannels; player->sampwidth = sampwidth; player->periodsize = periodsize; player->buffersize = buffsz; player->buffer = buff; return player; }
bool open() { // Open the Alsa playback device. int err=-1,count=0; unsigned int freakuency = frequency; while((count < 5) && (err < 0)) { err = snd_pcm_open ( &handle, ALSA_OUTPUT_NAME, SND_PCM_STREAM_PLAYBACK, 0 ); if(err < 0) { count++; qWarning()<<"QAudioOutput::open() err="<<err<<", count="<<count; } } if (( err < 0)||(handle == 0)) { qWarning( "QAudioOuput: snd_pcm_open: error %d", err ); return false; } snd_pcm_nonblock( handle, 0 ); // Set the desired HW parameters. snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca( &hwparams ); err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_any: err %d", err); return false; } err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_access: err %d", err); return false; } err = snd_pcm_hw_params_set_format( handle, hwparams, ( bitsPerSample == 16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8 ) ); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_format: err %d", err); return false; } err = snd_pcm_hw_params_set_channels ( handle, hwparams, (unsigned int)channels ); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_channels: err %d", err); return false; } err = snd_pcm_hw_params_set_rate_near ( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_rate_near: err %d", err); return false; } #ifndef ALSA_BUFFER_SIZE err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_get_buffer_size: err %d",err); } #else buffer_size = ALSA_BUFFER_SIZE; err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err %d",err); } #endif #ifndef ALSA_PERIOD_SIZE period_time = buffer_time/4; err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_period_time_near: err %d",err); } #else period_size = ALSA_PERIOD_SIZE; err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, 0); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params_set_period_size_near: err %d",err); } #endif err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_hw_params: err %d", err); return false; } int dir; unsigned int vval, vval2; snd_pcm_access_t val; snd_pcm_format_t fval; snd_pcm_subformat_t sval; qLog(QAudioOutput) << "PCM handle name =" << snd_pcm_name(handle); qLog(QAudioOutput) << "PCM state =" << snd_pcm_state_name(snd_pcm_state(handle)); snd_pcm_hw_params_get_access(hwparams,&val); vval = (unsigned int)val; if ( (int)vval != (int)access ) { qWarning( "QAudioInput: access type not set, want %s got %s", snd_pcm_access_name((snd_pcm_access_t)access), snd_pcm_access_name((snd_pcm_access_t)vval) ); access = (snd_pcm_access_t)vval; } qLog(QAudioOutput) << "access type =" << snd_pcm_access_name((snd_pcm_access_t)vval); snd_pcm_hw_params_get_format(hwparams, &fval); vval = (unsigned int)fval; if ( (int)vval != (int)format ) { qWarning( "QAudioInput: format type not set, want %s got %s", snd_pcm_format_name((snd_pcm_format_t)format), snd_pcm_format_name((snd_pcm_format_t)vval) ); format = (snd_pcm_format_t)vval; } qLog(QAudioOutput) << QString("format = '%1' (%2)").arg(snd_pcm_format_name((snd_pcm_format_t)vval)) .arg(snd_pcm_format_description((snd_pcm_format_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_subformat(hwparams,&sval); vval = (unsigned int)sval; qLog(QAudioOutput) << QString("subformat = '%1' (%2)").arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval)) .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval)) .toLatin1().constData(); snd_pcm_hw_params_get_channels(hwparams, &vval); if ( (int)vval != (int)channels ) { qWarning( "QAudioInput: channels type not set, want %d got %d",channels,vval); channels = vval; } qLog(QAudioOutput) << "channels =" << vval; snd_pcm_hw_params_get_rate(hwparams, &vval, &dir); if ( (int)vval != (int)frequency ) { qWarning( "QAudioInput: frequency type not set, want %d got %d",frequency,vval); frequency = vval; } qLog(QAudioOutput) << "rate =" << vval << "bps"; snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); qLog(QAudioOutput) << "period time =" << period_time << "us"; snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir); qLog(QAudioOutput) << "period size =" << (int)period_size << "frames"; qLog(QAudioOutput) << "buffer time =" << (int)buffer_time << "us"; qLog(QAudioOutput) << "buffer size =" << (int)buffer_size << "frames"; snd_pcm_hw_params_get_periods(hwparams, &vval, &dir); periods = vval; qLog(QAudioOutput) << "periods per buffer =" << vval << "frames"; snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2); qLog(QAudioOutput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData(); vval = snd_pcm_hw_params_get_sbits(hwparams); qLog(QAudioOutput) << "significant bits =" << vval; vval = snd_pcm_hw_params_is_batch(hwparams); qLog(QAudioOutput) << "is batch =" << vval; vval = snd_pcm_hw_params_is_block_transfer(hwparams); qLog(QAudioOutput) << "is block transfer =" << vval; vval = snd_pcm_hw_params_is_double(hwparams); qLog(QAudioOutput) << "is double =" << vval; vval = snd_pcm_hw_params_is_half_duplex(hwparams); qLog(QAudioOutput) << "is half duplex =" << vval; vval = snd_pcm_hw_params_is_joint_duplex(hwparams); qLog(QAudioOutput) << "is joint duplex =" << vval; vval = snd_pcm_hw_params_can_overrange(hwparams); qLog(QAudioOutput) << "can overrange =" << vval; vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams); qLog(QAudioOutput) << "can mmap =" << vval; vval = snd_pcm_hw_params_can_pause(hwparams); qLog(QAudioOutput) << "can pause =" << vval; vval = snd_pcm_hw_params_can_resume(hwparams); qLog(QAudioOutput) << "can resume =" << vval; vval = snd_pcm_hw_params_can_sync_start(hwparams); qLog(QAudioOutput) << "can sync start =" << vval; // Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_sw_params_current(handle, swparams); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_sw_params_current: err %d",err); } err = snd_pcm_sw_params_set_start_threshold(handle,swparams,buffer_size); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_sw_params_set_start_threshold: err %d",err); } err = snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_size); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_sw_params_set_stop_threshold: err %d",err); } err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_sw_params_set_avail_min: err %d",err); } err = snd_pcm_sw_params(handle, swparams); if ( err < 0 ) { qWarning( "QAudioOutput: snd_pcm_sw_params: err %d",err); } // Prepare for audio output. snd_pcm_prepare( handle ); return true; }
static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) { int status; snd_pcm_hw_params_t *params; snd_pcm_format_t format; snd_pcm_uframes_t frames; Uint16 test_format; /* Open the audio device */ status = snd_pcm_open(&pcm_handle, get_audio_device(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if ( status < 0 ) { SDL_SetError("Couldn't open audio device: %s", snd_strerror(status)); return(-1); } /* Figure out what the hardware is capable of */ snd_pcm_hw_params_alloca(¶ms); status = snd_pcm_hw_params_any(pcm_handle, params); if ( status < 0 ) { SDL_SetError("Couldn't get hardware config: %s", snd_strerror(status)); ALSA_CloseAudio(this); return(-1); } /* SDL only uses interleaved sample output */ status = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if ( status < 0 ) { SDL_SetError("Couldn't set interleaved access: %s", snd_strerror(status)); ALSA_CloseAudio(this); return(-1); } /* Try for a closest match on audio format */ status = -1; for ( test_format = SDL_FirstAudioFormat(spec->format); test_format && (status < 0); ) { switch ( test_format ) { case AUDIO_U8: format = SND_PCM_FORMAT_U8; break; case AUDIO_S8: format = SND_PCM_FORMAT_S8; break; case AUDIO_S16LSB: format = SND_PCM_FORMAT_S16_LE; break; case AUDIO_S16MSB: format = SND_PCM_FORMAT_S16_BE; break; case AUDIO_U16LSB: format = SND_PCM_FORMAT_U16_LE; break; case AUDIO_U16MSB: format = SND_PCM_FORMAT_U16_BE; break; default: format = 0; break; } if ( format != 0 ) { status = snd_pcm_hw_params_set_format(pcm_handle, params, format); } if ( status < 0 ) { test_format = SDL_NextAudioFormat(); } } if ( status < 0 ) { SDL_SetError("Couldn't find any hardware audio formats"); ALSA_CloseAudio(this); return(-1); } spec->format = test_format; /* Set the number of channels */ status = snd_pcm_hw_params_set_channels(pcm_handle, params, spec->channels); if ( status < 0 ) { status = snd_pcm_hw_params_get_channels(params); if ( (status <= 0) || (status > 2) ) { SDL_SetError("Couldn't set audio channels"); ALSA_CloseAudio(this); return(-1); } spec->channels = status; } /* Set the audio rate */ status = snd_pcm_hw_params_set_rate_near(pcm_handle, params, spec->freq, NULL); if ( status < 0 ) { SDL_SetError("Couldn't set audio frequency: %s", snd_strerror(status)); ALSA_CloseAudio(this); return(-1); } spec->freq = status; /* Set the buffer size, in samples */ frames = spec->samples; frames = snd_pcm_hw_params_set_period_size_near(pcm_handle, params, frames, NULL); spec->samples = frames; snd_pcm_hw_params_set_periods_near(pcm_handle, params, 2, NULL); /* "set" the hardware with the desired parameters */ status = snd_pcm_hw_params(pcm_handle, params); if ( status < 0 ) { SDL_SetError("Couldn't set audio parameters: %s", snd_strerror(status)); ALSA_CloseAudio(this); return(-1); } /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(spec); /* Allocate mixing buffer */ mixlen = spec->size; mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); if ( mixbuf == NULL ) { ALSA_CloseAudio(this); return(-1); } memset(mixbuf, spec->silence, spec->size); /* Get the parent process id (we're the parent of the audio thread) */ parent = getpid(); /* Switch to blocking mode for playback */ snd_pcm_nonblock(pcm_handle, 0); /* We're ready to rock and roll. :-) */ return(0); }
int record(int size,char *serverString) { unsigned int pcm, tmp, dir; int rate, channels, seconds; snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames; char *buff,*buf; int buff_size, loops; int fp; /*if (argc < 4) { printf("Usage: %s <sample_rate> <channels> <seconds>\n", argv[0]); return -1; }*/ rate = 8000;//atoi(argv[1]); channels = 1;//atoi(argv[2]); seconds = 10;//atoi(argv[3]); /* Open the PCM device in playback mode */ if (pcm = snd_pcm_open(&pcm_handle, "default" , SND_PCM_STREAM_PLAYBACK, 0) < 0) printf("ERROR: Can't open \"%s\" PCM device. %s\n", "default", snd_strerror(pcm)); /* 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 */ if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,SND_PCM_ACCESS_RW_INTERLEAVED) < 0) printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm)); if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,SND_PCM_FORMAT_U8) < 0) printf("ERROR: Can't set format. %s\n", snd_strerror(pcm)); if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0) printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm)); if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0) printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm)); /* Write parameters */ if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0) printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm)); /* Resume information */ printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle)); printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle))); snd_pcm_hw_params_get_channels(params, &tmp); printf("channels: %i ", tmp); if (tmp == 1) printf("(mono)\n"); else if (tmp == 2) printf("(stereo)\n"); snd_pcm_hw_params_get_rate(params, &tmp, 0); printf("rate: %d bps\n", tmp); printf("seconds: %d\n", seconds); /* Allocate buffer to hold single period */ snd_pcm_hw_params_get_period_size(params, &frames, 0); buff_size = frames * channels * 2 /* 2 -> sample size */; buff = (char *) malloc(buff_size*3); size = frames * channels * 2 /* 2 -> sample size */; buf = (char *) realloc((void*)serverString,(size*3)); snd_pcm_hw_params_get_period_time(params, &tmp, NULL); //fp=open("222.wav",O_RDONLY); for (loops = (seconds * 1000000) / tmp; loops > 0; loops--) { /* if (pcm = read(fp, buff, buff_size) == 0) { printf("Early end of file.\n"); //return 0; } */ if (pcm = snd_pcm_writei(pcm_handle, buf, frames) == -EPIPE) { printf("XRUN.\n"); snd_pcm_prepare(pcm_handle); } else if(pcm < 0) { printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm)); } } snd_pcm_drain(pcm_handle); snd_pcm_close(pcm_handle); free(buff); return 0; }
int main(int argc, char ** argv) { // Variable declaration int rc; char * buffer; int buffer_size; int periods_per_buffer; snd_pcm_t *handle; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames; unsigned int channels; unsigned int rate; wav_header * wav_header_info; FILE * fp; // Argument parsing if (argc != 2) { printf("Incorrect usage: Enter filename of the wav file you want to play as an argument: %s filename.txt\n", argv[0]); return 1; } // Open wav file to read fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("ERROR: %s does not exist, or cannot be opened.\n", argv[1]); return 1; } wav_header_info = malloc(44); fread(wav_header_info, 1, 44, fp); // print_wav_header(wav_header_info); // Assign variables that were read from the wave file channels = wav_header_info->number_of_channels; rate = wav_header_info->sample_rate; periods_per_buffer = 2; // Down to user preference, depending on size of internal ring buffer of ALSA // Open PCM device for playback if ((rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("ERROR: Cannot open pcm device. %s\n", snd_strerror(rc)); } // Allocate hardware parameters if ((rc = snd_pcm_hw_params_malloc(¶ms)) < 0) { printf("ERROR: Cannot allocate hardware parameters. %s\n", snd_strerror(rc)); } // Initialize parameters with default values if ((rc = snd_pcm_hw_params_any(handle, params)) < 0) { printf("ERROR: Cannot initialize hardware parameters. %s\n", snd_strerror(rc)); } // Setting hardware parameters if ((rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { printf("ERROR: Cannot set interleaved mode. %s\n", snd_strerror(rc)); } if ((rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0) { printf("ERROR: Cannot set PCM format. %s\n", snd_strerror(rc)); } if ((rc = snd_pcm_hw_params_set_channels_near(handle, params, &channels)) < 0) { printf("ERROR: Cannot set number of channels. %s\n", snd_strerror(rc)); } if ((rc = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0) { printf("ERROR: Cannot set plyabck rate. %s\n", snd_strerror(rc)); } if ((rc = snd_pcm_hw_params(handle, params)) < 0) { printf("ERROR: Cannot set hardware parameters. %s\n", snd_strerror(rc)); } // Get hardware parameters if ((rc = snd_pcm_hw_params_get_period_size(params, &frames, 0)) < 0) { printf("Playback ERROR: Can't get period size. %s\n", snd_strerror(rc)); } printf("Frames: %lu\n", frames); if ((rc = snd_pcm_hw_params_get_channels(params, &channels)) < 0) { printf("Playback ERROR: Can't get channel number. %s\n", snd_strerror(rc)); } if ((rc = snd_pcm_hw_params_get_rate(params, &rate, 0)) < 0) { printf("ERROR: Cannot get rate. %s\n", snd_strerror(rc)); } // Free paraemeters snd_pcm_hw_params_free(params); // Create buffer buffer_size = frames * periods_per_buffer * channels * sizeof(int16_t); /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(buffer_size); // Send info to ALSA //while ((rc = read(0, buffer, buffer_size)) != 0) while (rc = fread(buffer, 1, periods_per_buffer * frames * channels * sizeof(int16_t), fp) != 0) { rc = snd_pcm_writei(handle, buffer, frames * periods_per_buffer); if (rc == -EPIPE) { fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { printf("ERROR: Cannot write to playback device. %s\n", strerror(rc)); } } printf("Info set: Device is now draining...\n"); snd_pcm_drain(handle); printf("Done playing, closing connections.\n"); snd_pcm_close(handle); free(wav_header_info); free(buffer); fclose(fp); return 0; }
int ai_alsa_setup(audio_in_t *ai) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size, period_size; int err; int dir; unsigned int rate; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(ai->alsa.handle, params); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Broken configuration for this PCM: no configurations available.\n"); return -1; } err = snd_pcm_hw_params_set_access(ai->alsa.handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Access type not available.\n"); return -1; } err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Sample format not available.\n"); return -1; } err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels); if (err < 0) { snd_pcm_hw_params_get_channels(params, &ai->channels); mp_tmsg(MSGT_TV, MSGL_ERR, "Channel count not available - reverting to default: %d\n", ai->channels); } else { ai->channels = ai->req_channels; } dir = 0; rate = ai->req_samplerate; err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set samplerate.\n"); } ai->samplerate = rate; dir = 0; ai->alsa.buffer_time = 1000000; err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params, &ai->alsa.buffer_time, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set buffer time.\n"); } dir = 0; ai->alsa.period_time = ai->alsa.buffer_time / 4; err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params, &ai->alsa.period_time, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set period time.\n"); } err = snd_pcm_hw_params(ai->alsa.handle, params); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install hardware parameters: %s", snd_strerror(err)); snd_pcm_hw_params_dump(params, ai->alsa.log); return -1; } dir = -1; snd_pcm_hw_params_get_period_size(params, &period_size, &dir); snd_pcm_hw_params_get_buffer_size(params, &buffer_size); ai->alsa.chunk_size = period_size; if (period_size == buffer_size) { mp_tmsg(MSGT_TV, MSGL_ERR, "Can't use period equal to buffer size (%u == %lu)\n", ai->alsa.chunk_size, (long)buffer_size); return -1; } snd_pcm_sw_params_current(ai->alsa.handle, swparams); err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size); err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0); err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size); if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install software parameters:\n"); snd_pcm_sw_params_dump(swparams, ai->alsa.log); return -1; } if (mp_msg_test(MSGT_TV, MSGL_V)) { snd_pcm_dump(ai->alsa.handle, ai->alsa.log); } ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels; ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8; ai->samplesize = ai->alsa.bits_per_sample; ai->bytes_per_sample = ai->alsa.bits_per_sample/8; return 0; }
int ai_alsa_setup(audio_in_t *ai) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; int buffer_size; int err; unsigned int rate; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(ai->alsa.handle, params); if (err < 0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig); return -1; } err = snd_pcm_hw_params_set_access(ai->alsa.handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType); return -1; } err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt); return -1; } err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels); if (err < 0) { ai->channels = snd_pcm_hw_params_get_channels(params); mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount, ai->channels); } else { ai->channels = ai->req_channels; } err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, ai->req_samplerate, 0); assert(err >= 0); rate = err; ai->samplerate = rate; ai->alsa.buffer_time = 1000000; ai->alsa.buffer_time = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params, ai->alsa.buffer_time, 0); assert(ai->alsa.buffer_time >= 0); ai->alsa.period_time = ai->alsa.buffer_time / 4; ai->alsa.period_time = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params, ai->alsa.period_time, 0); assert(ai->alsa.period_time >= 0); err = snd_pcm_hw_params(ai->alsa.handle, params); if (err < 0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams); snd_pcm_hw_params_dump(params, ai->alsa.log); return -1; } ai->alsa.chunk_size = snd_pcm_hw_params_get_period_size(params, 0); buffer_size = snd_pcm_hw_params_get_buffer_size(params); if (ai->alsa.chunk_size == buffer_size) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size); return -1; } snd_pcm_sw_params_current(ai->alsa.handle, swparams); err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0); assert(err >= 0); err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size); assert(err >= 0); err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0); assert(err >= 0); err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size); assert(err >= 0); assert(err >= 0); if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) { mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams); snd_pcm_sw_params_dump(swparams, ai->alsa.log); return -1; } if (mp_msg_test(MSGT_TV, MSGL_V)) { snd_pcm_dump(ai->alsa.handle, ai->alsa.log); } ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels; ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8; ai->samplesize = ai->alsa.bits_per_sample; ai->bytes_per_sample = ai->alsa.bits_per_sample/8; return 0; }