Example #1
0
// 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
}
Example #2
0
// Write writes a buffer of data to a playback device.
func (p *PlaybackDevice) Write(buffer interface{}) (samples int, err error) {
	bufferType := reflect.TypeOf(buffer)
	if !(bufferType.Kind() == reflect.Array ||
		bufferType.Kind() == reflect.Slice) {
		return 0, errors.New("Write requires an array type")
	}

	sizeError := errors.New("Write requires a matching sample size")
	switch bufferType.Elem().Kind() {
	case reflect.Int8:
		if p.formatSampleSize() != 1 {
			return 0, sizeError
		}
	case reflect.Int16:
		if p.formatSampleSize() != 2 {
			return 0, sizeError
		}
	case reflect.Int32, reflect.Float32:
		if p.formatSampleSize() != 4 {
			return 0, sizeError
		}
	case reflect.Float64:
		if p.formatSampleSize() != 8 {
			return 0, sizeError
		}
	default:
		return 0, errors.New("Write 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 / p.Channels)
	bufPtr := unsafe.Pointer(sliceData.Index(0).Addr().Pointer())

	ret := C.snd_pcm_writei(p.h, bufPtr, frames)
	if ret == -C.EPIPE {
		C.snd_pcm_prepare(p.h)
		return 0, ErrUnderrun
	} else if ret < 0 {
		return 0, createError("write error", C.int(ret))
	}
	samples = int(ret) * p.Channels
	return
}