277 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright ÂGo Opus Authors (see AUTHORS file)
 | |
| //
 | |
| // License for use of this code is detailed in the LICENSE file
 | |
| 
 | |
| package opus
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| /*
 | |
| #cgo pkg-config: opus
 | |
| #include <opus.h>
 | |
| 
 | |
| int
 | |
| bridge_decoder_get_last_packet_duration(OpusDecoder *st, opus_int32 *samples)
 | |
| {
 | |
| 	return opus_decoder_ctl(st, OPUS_GET_LAST_PACKET_DURATION(samples));
 | |
| }
 | |
| */
 | |
| import "C"
 | |
| 
 | |
| var errDecUninitialized = fmt.Errorf("opus decoder uninitialized")
 | |
| 
 | |
| type Decoder struct {
 | |
| 	p *C.struct_OpusDecoder
 | |
| 	// Same purpose as encoder struct
 | |
| 	mem         []byte
 | |
| 	sample_rate int
 | |
| 	channels    int
 | |
| }
 | |
| 
 | |
| // NewDecoder allocates a new Opus decoder and initializes it with the
 | |
| // appropriate parameters. All related memory is managed by the Go GC.
 | |
| func NewDecoder(sample_rate int, channels int) (*Decoder, error) {
 | |
| 	var dec Decoder
 | |
| 	err := dec.Init(sample_rate, channels)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &dec, nil
 | |
| }
 | |
| 
 | |
| func (dec *Decoder) Init(sample_rate int, channels int) error {
 | |
| 	if dec.p != nil {
 | |
| 		return fmt.Errorf("opus decoder already initialized")
 | |
| 	}
 | |
| 	if channels != 1 && channels != 2 {
 | |
| 		return fmt.Errorf("Number of channels must be 1 or 2: %d", channels)
 | |
| 	}
 | |
| 	size := C.opus_decoder_get_size(C.int(channels))
 | |
| 	dec.sample_rate = sample_rate
 | |
| 	dec.channels = channels
 | |
| 	dec.mem = make([]byte, size)
 | |
| 	dec.p = (*C.OpusDecoder)(unsafe.Pointer(&dec.mem[0]))
 | |
| 	errno := C.opus_decoder_init(
 | |
| 		dec.p,
 | |
| 		C.opus_int32(sample_rate),
 | |
| 		C.int(channels))
 | |
| 	if errno != 0 {
 | |
| 		return Error(errno)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Decode encoded Opus data into the supplied buffer. On success, returns the
 | |
| // number of samples correctly written to the target buffer.
 | |
| func (dec *Decoder) Decode(data []byte, pcm []int16) (int, error) {
 | |
| 	if dec.p == nil {
 | |
| 		return 0, errDecUninitialized
 | |
| 	}
 | |
| 	if len(data) == 0 {
 | |
| 		return 0, fmt.Errorf("opus: no data supplied")
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return 0, fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return 0, fmt.Errorf("opus: target buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode(
 | |
| 		dec.p,
 | |
| 		(*C.uchar)(&data[0]),
 | |
| 		C.opus_int32(len(data)),
 | |
| 		(*C.opus_int16)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		0))
 | |
| 	if n < 0 {
 | |
| 		return 0, Error(n)
 | |
| 	}
 | |
| 	return n, nil
 | |
| }
 | |
| 
 | |
| // Decode encoded Opus data into the supplied buffer. On success, returns the
 | |
| // number of samples correctly written to the target buffer.
 | |
| func (dec *Decoder) DecodeFloat32(data []byte, pcm []float32) (int, error) {
 | |
| 	if dec.p == nil {
 | |
| 		return 0, errDecUninitialized
 | |
| 	}
 | |
| 	if len(data) == 0 {
 | |
| 		return 0, fmt.Errorf("opus: no data supplied")
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return 0, fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return 0, fmt.Errorf("opus: target buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode_float(
 | |
| 		dec.p,
 | |
| 		(*C.uchar)(&data[0]),
 | |
| 		C.opus_int32(len(data)),
 | |
| 		(*C.float)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		0))
 | |
| 	if n < 0 {
 | |
| 		return 0, Error(n)
 | |
| 	}
 | |
| 	return n, nil
 | |
| }
 | |
| 
 | |
| // DecodeFEC encoded Opus data into the supplied buffer with forward error
 | |
| // correction.
 | |
| //
 | |
| // It is to be used on the packet directly following the lost one.  The supplied
 | |
| // buffer needs to be exactly the duration of audio that is missing
 | |
| //
 | |
| // When a packet is considered "lost", DecodeFEC can be called on the next
 | |
| // packet in order to try and recover some of the lost data. The PCM needs to be
 | |
| // exactly the duration of audio that is missing.  `LastPacketDuration()` can be
 | |
| // used on the decoder to get the length of the last packet.  Note also that in
 | |
| // order to use this feature the encoder needs to be configured with
 | |
| // SetInBandFEC(true) and SetPacketLossPerc(x) options.
 | |
| //
 | |
| // Note that DecodeFEC automatically falls back to PLC when no FEC data is
 | |
| // available in the provided packet.
 | |
| func (dec *Decoder) DecodeFEC(data []byte, pcm []int16) error {
 | |
| 	if dec.p == nil {
 | |
| 		return errDecUninitialized
 | |
| 	}
 | |
| 	if len(data) == 0 {
 | |
| 		return fmt.Errorf("opus: no data supplied")
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return fmt.Errorf("opus: target buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode(
 | |
| 		dec.p,
 | |
| 		(*C.uchar)(&data[0]),
 | |
| 		C.opus_int32(len(data)),
 | |
| 		(*C.opus_int16)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		1))
 | |
| 	if n < 0 {
 | |
| 		return Error(n)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // DecodeFECFloat32 encoded Opus data into the supplied buffer with forward error
 | |
| // correction. It is to be used on the packet directly following the lost one.
 | |
| // The supplied buffer needs to be exactly the duration of audio that is missing
 | |
| func (dec *Decoder) DecodeFECFloat32(data []byte, pcm []float32) error {
 | |
| 	if dec.p == nil {
 | |
| 		return errDecUninitialized
 | |
| 	}
 | |
| 	if len(data) == 0 {
 | |
| 		return fmt.Errorf("opus: no data supplied")
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return fmt.Errorf("opus: target buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode_float(
 | |
| 		dec.p,
 | |
| 		(*C.uchar)(&data[0]),
 | |
| 		C.opus_int32(len(data)),
 | |
| 		(*C.float)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		1))
 | |
| 	if n < 0 {
 | |
| 		return Error(n)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // DecodePLC recovers a lost packet using Opus Packet Loss Concealment feature.
 | |
| //
 | |
| // The supplied buffer needs to be exactly the duration of audio that is missing.
 | |
| // When a packet is considered "lost", `DecodePLC` and `DecodePLCFloat32` methods
 | |
| // can be called in order to obtain something better sounding than just silence.
 | |
| // The PCM needs to be exactly the duration of audio that is missing.
 | |
| // `LastPacketDuration()` can be used on the decoder to get the length of the
 | |
| // last packet.
 | |
| //
 | |
| // This option does not require any additional encoder options. Unlike FEC,
 | |
| // PLC does not introduce additional latency. It is calculated from the previous
 | |
| // packet, not from the next one.
 | |
| func (dec *Decoder) DecodePLC(pcm []int16) error {
 | |
| 	if dec.p == nil {
 | |
| 		return errDecUninitialized
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return fmt.Errorf("opus: output buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode(
 | |
| 		dec.p,
 | |
| 		nil,
 | |
| 		0,
 | |
| 		(*C.opus_int16)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		0))
 | |
| 	if n < 0 {
 | |
| 		return Error(n)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // DecodePLCFloat32 recovers a lost packet using Opus Packet Loss Concealment feature.
 | |
| // The supplied buffer needs to be exactly the duration of audio that is missing.
 | |
| func (dec *Decoder) DecodePLCFloat32(pcm []float32) error {
 | |
| 	if dec.p == nil {
 | |
| 		return errDecUninitialized
 | |
| 	}
 | |
| 	if len(pcm) == 0 {
 | |
| 		return fmt.Errorf("opus: target buffer empty")
 | |
| 	}
 | |
| 	if cap(pcm)%dec.channels != 0 {
 | |
| 		return fmt.Errorf("opus: output buffer capacity must be multiple of channels")
 | |
| 	}
 | |
| 	n := int(C.opus_decode_float(
 | |
| 		dec.p,
 | |
| 		nil,
 | |
| 		0,
 | |
| 		(*C.float)(&pcm[0]),
 | |
| 		C.int(cap(pcm)/dec.channels),
 | |
| 		0))
 | |
| 	if n < 0 {
 | |
| 		return Error(n)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // LastPacketDuration gets the duration (in samples)
 | |
| // of the last packet successfully decoded or concealed.
 | |
| func (dec *Decoder) LastPacketDuration() (int, error) {
 | |
| 	var samples C.opus_int32
 | |
| 	res := C.bridge_decoder_get_last_packet_duration(dec.p, &samples)
 | |
| 	if res != C.OPUS_OK {
 | |
| 		return 0, Error(res)
 | |
| 	}
 | |
| 	return int(samples), nil
 | |
| }
 | |
| 
 | |
| // Reset reinitializes the decoder with the existing parameters
 | |
| func (dec *Decoder) Reset() error {
 | |
|     // Store current parameters
 | |
|     sample_rate := dec.sample_rate
 | |
|     channels := dec.channels
 | |
|     
 | |
|     // Clear the decoder
 | |
|     dec.p = nil
 | |
|     dec.mem = nil
 | |
|     
 | |
|     // Reinitialize with same parameters
 | |
|     return dec.Init(sample_rate, channels)
 | |
| }
 |