// Open opens a stream. func (handle *Handle) Open(device string, streamType StreamType, mode int) error { cDevice := C.CString(device) defer C.free(unsafe.Pointer(cDevice)) err := C.snd_pcm_open(&(handle.cHandle), cDevice, _Ctype_snd_pcm_stream_t(streamType), _Ctype_int(mode)) if err < 0 { return errors.New(fmt.Sprintf("Cannot open audio device '%s'. %s", device, strError(err))) } return nil }
func (d *device) createDevice(deviceName string, channels int, format Format, rate int, playback bool, bufferParams BufferParams) (err error) { deviceCString := C.CString(deviceName) defer C.free(unsafe.Pointer(deviceCString)) var ret C.int if playback { ret = C.snd_pcm_open(&d.h, deviceCString, C.SND_PCM_STREAM_PLAYBACK, 0) } else { ret = C.snd_pcm_open(&d.h, deviceCString, C.SND_PCM_STREAM_CAPTURE, 0) } if ret < 0 { return fmt.Errorf("could not open ALSA device %s", deviceName) } runtime.SetFinalizer(d, (*device).Close) var hwParams *C.snd_pcm_hw_params_t ret = C.snd_pcm_hw_params_malloc(&hwParams) if ret < 0 { return createError("could not alloc hw params", ret) } defer C.snd_pcm_hw_params_free(hwParams) ret = C.snd_pcm_hw_params_any(d.h, hwParams) if ret < 0 { return createError("could not set default hw params", ret) } ret = C.snd_pcm_hw_params_set_access(d.h, hwParams, C.SND_PCM_ACCESS_RW_INTERLEAVED) if ret < 0 { return createError("could not set access params", ret) } ret = C.snd_pcm_hw_params_set_format(d.h, hwParams, C.snd_pcm_format_t(format)) if ret < 0 { return createError("could not set format params", ret) } ret = C.snd_pcm_hw_params_set_channels(d.h, hwParams, C.uint(channels)) if ret < 0 { return createError("could not set channels params", ret) } ret = C.snd_pcm_hw_params_set_rate(d.h, hwParams, C.uint(rate), 0) if ret < 0 { return createError("could not set rate params", ret) } var bufferSize = C.snd_pcm_uframes_t(bufferParams.BufferFrames) if bufferParams.BufferFrames == 0 { // Default buffer size: max buffer size ret = C.snd_pcm_hw_params_get_buffer_size_max(hwParams, &bufferSize) if ret < 0 { return createError("could not get buffer size", ret) } } ret = C.snd_pcm_hw_params_set_buffer_size_near(d.h, hwParams, &bufferSize) if ret < 0 { return createError("could not set buffer size", ret) } // Default period size: 1/8 of a second var periodFrames = C.snd_pcm_uframes_t(rate / 8) if bufferParams.PeriodFrames > 0 { periodFrames = C.snd_pcm_uframes_t(bufferParams.PeriodFrames) } else if bufferParams.Periods > 0 { periodFrames = C.snd_pcm_uframes_t(int(bufferSize) / bufferParams.Periods) } ret = C.snd_pcm_hw_params_set_period_size_near(d.h, hwParams, &periodFrames, nil) if ret < 0 { return createError("could not set period size", ret) } var periods = C.uint(0) ret = C.snd_pcm_hw_params_get_periods(hwParams, &periods, nil) if ret < 0 { return createError("could not get periods", ret) } ret = C.snd_pcm_hw_params(d.h, hwParams) if ret < 0 { return createError("could not set hw params", ret) } d.frames = int(periodFrames) d.Channels = channels d.Format = format d.Rate = rate d.BufferParams.BufferFrames = int(bufferSize) d.BufferParams.PeriodFrames = int(periodFrames) d.BufferParams.Periods = int(periods) return }