// Read reads samples into a buffer and returns the amount read. func (c *CaptureDevice) Read(buffer interface{}) (samples int, err error) { bufferType := reflect.TypeOf(buffer) if !(bufferType.Kind() == reflect.Array || bufferType.Kind() == reflect.Slice) { return 0, errors.New("Read requires an array type") } sizeError := errors.New("Read requires a matching sample size") switch bufferType.Elem().Kind() { case reflect.Int8: if c.formatSampleSize() != 1 { return 0, sizeError } case reflect.Int16: if c.formatSampleSize() != 2 { return 0, sizeError } case reflect.Int32, reflect.Float32: if c.formatSampleSize() != 4 { return 0, sizeError } case reflect.Float64: if c.formatSampleSize() != 8 { return 0, sizeError } default: return 0, errors.New("Read does not support this format") } val := reflect.ValueOf(buffer) length := val.Len() sliceData := val.Slice(0, length) var frames = C.snd_pcm_uframes_t(length / c.Channels) bufPtr := unsafe.Pointer(sliceData.Index(0).Addr().Pointer()) ret := C.snd_pcm_readi(c.h, bufPtr, frames) if ret == -C.EPIPE { C.snd_pcm_prepare(c.h) return 0, ErrOverrun } else if ret < 0 { return 0, createError("read error", C.int(ret)) } samples = int(ret) * c.Channels return }
// Write writes given PCM data. // Returns wrote value is total bytes was written. func (handle *Handle) Write(buf []byte) (wrote int, err error) { frames := len(buf) / handle.SampleSize() / handle.Channels w := C.snd_pcm_writei(handle.cHandle, unsafe.Pointer(&buf[0]), _Ctype_snd_pcm_uframes_t(frames)) // Underrun? Retry. if w == -C.EPIPE { C.snd_pcm_prepare(handle.cHandle) w = C.snd_pcm_writei(handle.cHandle, unsafe.Pointer(&buf[0]), _Ctype_snd_pcm_uframes_t(frames)) } if w < 0 { return 0, errors.New(fmt.Sprintf("Write failed. %s", strError(_Ctype_int(w)))) } wrote = int(w) wrote *= handle.FrameSize() return wrote, nil }