Coder Social home page Coder Social logo

opus's Introduction

Test

Go wrapper for Opus

This package provides Go bindings for the xiph.org C libraries libopus and libopusfile.

The C libraries and docs are hosted at https://opus-codec.org/. This package just handles the wrapping in Go, and is unaffiliated with xiph.org.

Features:

  • ✅ encode and decode raw PCM data to raw Opus data
  • ✅ useful when you control the recording device, and the playback
  • ✅ decode .opus and .ogg files into raw audio data ("PCM")
  • ✅ reuse the system libraries for opus decoding (libopus)
  • ✅ works easily on Linux, Mac and Docker; needs libs on Windows
  • ❌ does not create .opus or .ogg files (but feel free to send a PR)
  • ❌ does not work with .wav files (you need a separate .wav library for that)
  • ❌ no self-contained binary (you need the xiph.org libopus lib, e.g. through a package manager)
  • ❌ no cross compiling (because it uses CGo)

Good use cases:

  • 👍 you are writing a music player app in Go, and you want to play back .opus files
  • 👍 you record raw wav in a web app or mobile app, you encode it as Opus on the client, you send the opus to a remote webserver written in Go, and you want to decode it back to raw audio data on that server

Details

This wrapper provides a Go translation layer for three elements from the xiph.org opus libs:

  • encoders
  • decoders
  • files & streams

Import

import "gopkg.in/hraban/opus.v2"

Encoding

To encode raw audio to the Opus format, create an encoder first:

const sampleRate = 48000
const channels = 1 // mono; 2 for stereo

enc, err := opus.NewEncoder(sampleRate, channels, opus.AppVoIP)
if err != nil {
    ...
}

Then pass it some raw PCM data to encode.

Make sure that the raw PCM data you want to encode has a legal Opus frame size. This means it must be exactly 2.5, 5, 10, 20, 40 or 60 ms long. The number of bytes this corresponds to depends on the sample rate (see the libopus documentation).

var pcm []int16 = ... // obtain your raw PCM data somewhere
const bufferSize = 1000 // choose any buffer size you like. 1k is plenty.

// Check the frame size. You don't need to do this if you trust your input.
frameSize := len(pcm) // must be interleaved if stereo
frameSizeMs := float32(frameSize) / channels * 1000 / sampleRate
switch frameSizeMs {
case 2.5, 5, 10, 20, 40, 60:
    // Good.
default:
    return fmt.Errorf("Illegal frame size: %d bytes (%f ms)", frameSize, frameSizeMs)
}

data := make([]byte, bufferSize)
n, err := enc.Encode(pcm, data)
if err != nil {
    ...
}
data = data[:n] // only the first N bytes are opus data. Just like io.Reader.

Note that you must choose a target buffer size, and this buffer size will affect the encoding process:

Size of the allocated memory for the output payload. This may be used to impose an upper limit on the instant bitrate, but should not be used as the only bitrate control. Use OPUS_SET_BITRATE to control the bitrate.

-- https://opus-codec.org/docs/opus_api-1.1.3/group__opus__encoder.html

Decoding

To decode opus data to raw PCM format, first create a decoder:

dec, err := opus.NewDecoder(sampleRate, channels)
if err != nil {
    ...
}

Now pass it the opus bytes, and a buffer to store the PCM sound in:

var frameSizeMs float32 = ...  // if you don't know, go with 60 ms.
frameSize := channels * frameSizeMs * sampleRate / 1000
pcm := make([]int16, int(frameSize))
n, err := dec.Decode(data, pcm)
if err != nil {
    ...
}

// To get all samples (interleaved if multiple channels):
pcm = pcm[:n*channels] // only necessary if you didn't know the right frame size

// or access sample per sample, directly:
for i := 0; i < n; i++ {
    ch1 := pcm[i*channels+0]
    // For stereo output: copy ch1 into ch2 in mono mode, or deinterleave stereo
    ch2 := pcm[(i*channels)+(channels-1)]
}

To handle packet loss from an unreliable network, see the DecodePLC and DecodeFEC options.

Streams (and Files)

To decode a .opus file (or .ogg with Opus data), or to decode a "Opus stream" (which is a Ogg stream with Opus data), use the Stream interface. It wraps an io.Reader providing the raw stream bytes and returns the decoded Opus data.

A crude example for reading from a .opus file:

f, err := os.Open(fname)
if err != nil {
    ...
}
s, err := opus.NewStream(f)
if err != nil {
    ...
}
defer s.Close()
pcmbuf := make([]int16, 16384)
for {
    n, err = s.Read(pcmbuf)
    if err == io.EOF {
        break
    } else if err != nil {
        ...
    }
    pcm := pcmbuf[:n*channels]

    // send pcm to audio device here, or write to a .wav file

}

See https://godoc.org/gopkg.in/hraban/opus.v2#Stream for further info.

"My .ogg/.opus file doesn't play!" or "How do I play Opus in VLC / mplayer / ...?"

Note: this package only does encoding of your audio, to raw opus data. You can't just dump those all in one big file and play it back. You need extra info. First of all, you need to know how big each individual block is. Remember: opus data is a stream of encoded separate blocks, not one big stream of bytes. Second, you need meta-data: how many channels? What's the sampling rate? Frame size? Etc.

Look closely at the decoding sample code (not stream), above: we're passing all that meta-data in, hard-coded. If you just put all your encoded bytes in one big file and gave that to a media player, it wouldn't know what to do with it. It wouldn't even know that it's Opus data. It would just look like /dev/random.

What you need is a container format.

Compare it to video:

  • Encodings: MPEG[1234], VP9, H26[45], AV1
  • Container formats: .mkv, .avi, .mov, .ogv

For Opus audio, the most common container format is OGG, aka .ogg or .opus. You'll know OGG from OGG/Vorbis: that's Vorbis encoded audio in an OGG container. So for Opus, you'd call it OGG/Opus. But technically you could stick opus data in any container format that supports it, including e.g. Matroska (.mka for audio, you probably know it from .mkv for video).

Note: libopus, the C library that this wraps, technically comes with libopusfile, which can help with the creation of OGG/Opus streams from raw audio data. I just never needed it myself, so I haven't added the necessary code for it. If you find yourself adding it: send me a PR and we'll get it merged.

This libopus wrapper does come with code for decoding an OGG/Opus stream. Just not for writing one.

API Docs

Go wrapper API reference: https://godoc.org/gopkg.in/hraban/opus.v2

Full libopus C API reference: https://www.opus-codec.org/docs/opus_api-1.1.3/

For more examples, see the _test.go files.

Build & Installation

This package requires libopus and libopusfile development packages to be installed on your system. These are available on Debian based systems from aptitude as libopus-dev and libopusfile-dev, and on Mac OS X from homebrew.

They are linked into the app using pkg-config.

Debian, Ubuntu, ...:

sudo apt-get install pkg-config libopus-dev libopusfile-dev

Mac:

brew install pkg-config opus opusfile

Building Without libopusfile

This package can be built without libopusfile by using the build tag nolibopusfile. This enables the compilation of statically-linked binaries with no external dependencies on operating systems without a static libopusfile, such as Alpine Linux.

Note: this will disable all file and Stream APIs.

To enable this feature, add -tags nolibopusfile to your go build or go test commands:

# Build
go build -tags nolibopusfile ...

# Test
go test -tags nolibopusfile ./...

Using in Docker

If your Dockerized app has this library as a dependency (directly or indirectly), it will need to install the aforementioned packages, too.

This means you can't use the standard golang:*-onbuild images, because those will try to build the app from source before allowing you to install extra dependencies. Instead, try this as a Dockerfile:

# Choose any golang image, just make sure it doesn't have -onbuild
FROM golang:1

RUN apt-get update && apt-get -y install libopus-dev libopusfile-dev

# Everything below is copied manually from the official -onbuild image,
# with the ONBUILD keywords removed.

RUN mkdir -p /go/src/app
WORKDIR /go/src/app

CMD ["go-wrapper", "run"]
COPY . /go/src/app
RUN go-wrapper download
RUN go-wrapper install

For more information, see https://hub.docker.com/_/golang/.

Linking libopus and libopusfile

The opus and opusfile libraries will be linked into your application dynamically. This means everyone who uses the resulting binary will need those libraries available on their system. E.g. if you use this wrapper to write a music app in Go, everyone using that music app will need libopus and libopusfile on their system. On Debian systems the packages are called libopus0 and libopusfile0.

The "cleanest" way to do this is to publish your software through a package manager and specify libopus and libopusfile as dependencies of your program. If that is not an option, you can compile the dynamic libraries yourself and ship them with your software as seperate (.dll or .so) files.

On Linux, for example, you would need the libopus.so.0 and libopusfile.so.0 files in the same directory as the binary. Set your ELF binary's rpath to $ORIGIN (this is not a shell variable but elf magic):

patchelf --set-origin '$ORIGIN' your-app-binary

Now you can run the binary and it will automatically pick up shared library files from its own directory.

Wrap it all in a .zip, and ship.

I know there is a similar trick for Mac (involving prefixing the shared library names with ./, which is, arguably, better). And Windows... probably just picks up .dll files from the same dir by default? I don't know. But there are ways.

License

The licensing terms for the Go bindings are found in the LICENSE file. The authors and copyright holders are listed in the AUTHORS file.

The copyright notice uses range notation to indicate all years in between are subject to copyright, as well. This statement is necessary, apparently. For all those nefarious actors ready to abuse a copyright notice with incorrect notation, but thwarted by a mention in the README. Pfew!

opus's People

Contributors

bsponge avatar dh1tw avatar docmerlin avatar e-wave avatar gavv avatar hraban avatar kcaffrey avatar millfort avatar xudejian avatar ydnar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

opus's Issues

Declare constants as actual const

See #8 -- this might just be possible since a recent change in CGO or the underlying compilers. Must investigate why exactly this is now working and if we can assume it to keep working in the future.

"checkptr: unsafe pointer arithmetic" when using go race detector

Looks like some issue with uintptr when creating an Opus stream. Code does:

        r := bytes.NewReader(resp.AudioContent)
        s, err := opus.NewStream(r)
$ go build -race && ./run

fatal error: checkptr: unsafe pointer arithmetic

goroutine 230 [running]:
runtime.throw(0x12d4205, 0x23)
	/usr/local/go/src/runtime/panic.go:1116 +0x72 fp=0xc000519ae8 sp=0xc000519ab8 pc=0x4473d2
runtime.checkptrArithmetic(0x1, 0x0, 0x0, 0x0)
	/usr/local/go/src/runtime/checkptr.go:26 +0xce fp=0xc000519b18 sp=0xc000519ae8 pc=0x41a2ee
gopkg.in/hraban/opus%2ev2.(*Stream).Init.func1(0xc000498880, 0xc00037b1c8, 0x1)
	/home/chrb/go/pkg/mod/gopkg.in/hraban/[email protected]/stream.go:108 +0x66 fp=0xc000519b70 sp=0xc000519b18 pc=0xe256b6
gopkg.in/hraban/opus%2ev2.(*Stream).Init(0xc000498880, 0x15f9060, 0xc00071d230, 0x0, 0x0)
	/home/chrb/go/pkg/mod/gopkg.in/hraban/[email protected]/stream.go:112 +0x277 fp=0xc000519c40 sp=0xc000519b70 pc=0xe237d7
gopkg.in/hraban/opus%2ev2.NewStream(0x15f9060, 0xc00071d230, 0xc0000a7bf0, 0xc000502740, 0x0)
	/home/chrb/go/pkg/mod/gopkg.in/hraban/[email protected]/stream.go:75 +0xa0 fp=0xc000519c90 sp=0xc000519c40 pc=0xe234c0
main.sayGoogle(0xc0000198e0, 0x14, 0xc00031e4a0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/chrb/go/src/x/main.go:310 +0x568 fp=0xc000519e58 sp=0xc000519c90 pc=0x105a948
main.speak(0xc0000198e0, 0x14, 0xc000472000, 0xc0004a5a40)
	/home/chrb/go/src/x/main.go:488 +0x166 fp=0xc000519f70 sp=0xc000519e58 pc=0x105cf36
main.handleIncomingAudio.func4(0xc000472000, 0xc0004a5a40, 0xc0003074e0)
	/home/chrb/go/src/x/main.go:967 +0xeb fp=0xc000519fc8 sp=0xc000519f70 pc=0x10773bb
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000519fd0 sp=0xc000519fc8 pc=0x4792f1
created by main.handleIncomingAudio
	/home/chrb/go/src/x/main.go:962 +0x281

transfer pcm to opus

The pcm data I got is "[]byte" format, so how can I transfer it to "int16", and then encode to opus?
I have tried the code as below, but the output file is not opus file, and can't play.

func writeUSBDataToSamples(usbData []byte) []wav.Sample {
samples := make([]wav.Sample, 0)
for i := 0; i < len(usbData); i += 2 {
sample := wav.Sample{}
sample.Values[0] = int(usbData[i])
sample.Values[0] = int(usbData[i+1])
samples = append(samples, sample)
}
return samples
}

opusOutput := make([]byte, 0)
opusData := make([]byte, 4096)

encodedNumSum := 0
for encodedNumSum+OpusFrameSize < len(pcmInt16Data) {
	encodedNum, err := enc.Encode(pcmInt16Data[encodedNumSum:(encodedNumSum+OpusFrameSize)], opusData)
	if err != nil {
		fmt.Println("enc.Encode err ", err.Error())
		break
	}
	fmt.Println("encodedNum ", encodedNum)
	opusOutput = append(opusOutput, opusData[:encodedNum]...)
	encodedNumSum += OpusFrameSize
}
fmt.Println("opusOutput length ", len(opusOutput))
fopus, _ := os.OpenFile("output.opus", os.O_RDWR|os.O_CREATE, 0777)
fopus.Write(opusOutput)
fopus.Close()

Byte slice to int16 slice.

Hey everyone! Currently i'm trying to transcode ADTS to OPUS. And here's the problem.
I'm using this library to split an ADTS stream to PCMs - https://github.com/winlinvip/go-fdkaac . But PCMs it returns are []byte, not []int16.
What's the correct approach than to encode a bunch of PCMs in []byte (not []int16) ?
Thanks in advance!

How to complie in cross platform?

I try to go build for arm cpu,but output display error message. And go build for x86 cpu is ok.

env GOOS=linux GOARCH=arm go build   
# github.com/hraban/opus
/home/juice/code/golang/pkg/mod/github.com/hraban/[email protected]/streams_map.go:32:23: undefined: Stream
/home/juice/code/golang/pkg/mod/github.com/hraban/[email protected]/streams_map.go:36:40: undefined: Stream
/home/juice/code/golang/pkg/mod/github.com/hraban/[email protected]/streams_map.go:42:30: undefined: Stream
/home/juice/code/golang/pkg/mod/github.com/hraban/[email protected]/streams_map.go:53:31: undefined: Stream

Then i try to add build options -tags nolibopusfile

env GOOS=linux GOARCH=arm go build -tags nolibopusfile 
go build github.com/hraban/opus: build constraints exclude all Go files in /home/juice/code/golang/pkg/mod/github.com/hraban/[email protected]

wasm env

I need to do: pcm->opus with wasm,which seems not support now and hard in golang plans golang/go#40543 (maybe i miread?)

[root@localhost wasm_demo]# CGO_ENABLED=1 GOOS=js GOARCH=wasm go build -o hello.wasm -tags nolibopusfile cmd/03-js-call-go/main.go 
# runtime/cgo
cgo: unknown ptrSize for $GOARCH "wasm"

can i get some suggestions,thx

implicit declaration of function 'OPUS_GET_IN_DTX'

After trying to build my Go application using Docker I got the following error, not sure why am getting it though. Here's the error
#12 24.31 /go/pkg/mod/github.com/hraban/[email protected]/encoder.go: In function 'bridge_encoder_get_in_dtx': #12 24.31 /go/pkg/mod/github.com/hraban/[email protected]/encoder.go:31:30: warning: implicit declaration of function 'OPUS_GET_IN_DTX'; did you mean 'OPUS_GET_DTX'? [-Wimplicit-function-declaration] #12 24.31 return opus_encoder_ctl(st, OPUS_GET_IN_DTX(in_dtx)); #12 24.31 ^~~~~~~~~~~~~~~ #12 24.31 OPUS_GET_DTX #12 35.74 # command-line-arguments #12 35.74 /usr/local/go/pkg/tool/linux_arm64/link: running gcc failed: exit status 1 #12 35.74 /usr/bin/ld: /tmp/go-link-2185058262/000007.o: in function bridge_encoder_get_in_dtx':
#12 35.74 /go/pkg/mod/github.com/hraban/[email protected]/encoder.go:31: undefined reference to OPUS_GET_IN_DTX' #12 35.74 collect2: error: ld returned 1 exit status

To be able to reproduce the following error you, I used the following Dockerfile commands
`FROM golang:1.19-buster AS builder

WORKDIR /app

Copy your Go source code into the container

COPY . .

Install Opus and any other dependencies specific to your Alpine-based image

RUN apt-get update && apt-get -y install libopus-dev libopusfile-dev

Build the Go binary

RUN go build -o main main.go`
That's how you reproduce it

Strange distortion when decoding

Hi,

I'm remaking an app I wrote in Node in Golang.
The app receives proprietary voice packets, plucks out the opus data, and decodes it into PCM.

The Node app works great, it produces clear audio just as expected.

My Golang app is producing audio with weird bits of distortion. Popping, vaguely-robotic tone to the voice. It's strange.
I had them run in parallel to see where the disconnect was. The apps are behaving identically until they go to decode the opus data.

Here's a spectrogram comparison of the outputs (top is Go, bottom is Node):
audacity_XFyQ1VhfC1

You can see those thick vertical bars in the Golang output that aren't present in the other.

I've checked, double checked, and triple checked that I'm reading the voice data correctly, not dropping precision anywhere, and that I'm setting up the decoder properly. I've also verified that both containers have the same version of libopus-dev and libopusfile-dev.

I've tried Decoder.Decode and Decoder.DecodeFloat32 - same result.

My input opus audio is 1 channel at 24 kHz (16 bit).

I'm just at a loss of how else to debug this.
Does this info spark any ideas with you? Do you have any suggestions for how I could proceed?

Most of my code is decomposing the proprietary voice packets, so I'm not sure how helpful it'd be to share what I have, but I'd be happy to if you think it'd help.

Thank you!

How to destroy en(de)coder state?

There doesn't appear to be a binding for opus_encoder_destroy or the decoder equivalent. If I understand the docs correctly this indicates that the opus state object leaks memory each time an instance is created.

Or is there something hidden that I may have missed?

Decode: corrupted stream

Hello.
I have a file:
Container: Ogg
Codec: Opus
Chanells: Mono
Sample Rate: 48000
heyTel.ogg.zip

And this code:

func TestDecode(t *testing.T) {
    data, err := ioutil.ReadFile("heyTel.ogg")
    if err != nil {
        t.Fatal(err)
    }

    const sampleRate = 48000
    const frameSizeMS = 60
    const frameSize = sampleRate * frameSizeMS / 1000

    pcm := make([]int16, int(frameSize))

    dec, err := opus.NewDecoder(sampleRate, 1)
    if err != nil || dec == nil {
        t.Fatal(fmt.Errorf("Error creating new decoder: %v", err))
    }
    n, err := dec.Decode(data, pcm)
    if err != nil {
        t.Fatal(fmt.Errorf("Couldn't decode data: %v", err))
    }
    if len(pcm) != n {
        t.Fatal(fmt.Errorf("Length mismatch: %d samples in, %d out", len(pcm), n))
    }
}

But i get

Couldn't decode data: opus: corrupted stream

Could you tell me what's wrong? Thanks

Get audio from microphone and encode to ogg

Hi guys.

I would like to ask your help to get the live stream from the microphone and encode to ogg.

This is my code, this save two files one test.raw and work perfect, but output.ogg not play

// play -t raw -r 48000 -e signed -b 16 -c 1 test.raw
//

package main

import (
	"encoding/binary"
	"fmt"
	"os"
	"os/signal"
	"io/ioutil"

	"github.com/gordonklaus/portaudio"
	"gopkg.in/hraban/opus.v2"
)

func main() {
	var readBuffer = make([]byte, 0)
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)

	fileName := "test.raw"

	f, err := os.Create(fileName)
	chk(err)


	portaudio.Initialize()
	defer portaudio.Terminate()
	in := make([]int16, 960)
	stream, err := portaudio.OpenDefaultStream(1, 0, 48000, len(in), in)
	chk(err)
	defer stream.Close()

	chk(stream.Start())
	for {
		chk(stream.Read())
		
		chk(binary.Write(f, binary.LittleEndian, in))
		buf, encErr := encode(in)
		if err != nil {
			panic(encErr)
		}
		readBuffer = append(readBuffer, buf...)

		//fmt.Println(in, len(in))
		select {
		case <-sig:		
			// write the whole body at once
			err = ioutil.WriteFile("output.ogg", readBuffer, 0644)
			if err != nil {
				panic(err)
			}
			return
		default:
		}
	}
	chk(stream.Stop())
}

func encode(pcm []int16) ([]byte, error){	
	const sampleRate = 48000
	const channels = 1 // mono; 2 for stereo
	const bufferSize = 1000 // choose any buffer size you like. 1k is plenty.

	enc, err := opus.NewEncoder(sampleRate, channels, opus.AppVoIP)
	if err != nil {
      panic(err)
	}	

	// Check the frame size. You don't need to do this if you trust your input.
	frameSize := len(pcm) // must be interleaved if stereo
	frameSizeMs := float32(frameSize) / channels * 1000 / sampleRate
	switch frameSizeMs {
		case 2.5, 5, 10, 20, 40, 60:
    	// Good.
	default:
		fmt.Println("Illegal frame size: ", frameSize,  "bytes", frameSizeMs)
    	return nil, err
	}

	data := make([]byte, bufferSize)
	n, err := enc.Encode(pcm, data)
	if err != nil {
    	panic(err)
	}
	data = data[:n] // only the first N bytes are opus data. Just like io.Reader.
	fmt.Print(n, len(data))
	return data, err
}

func chk(err error) {
	if err != nil {
		panic(err)
	}
}

but when i try play output.ogg with mplayer.ogg i receive this message

MPlayer 1.3.0 (Debian), built with gcc-7 (C) 2000-2016 MPlayer Team
do_connect: could not connect to socket
connect: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing output.ogg.
libavformat version 57.83.100 (external)
libavformat file format detected.
[ogg @ 0xb6952e98]cannot find sync word
LAVF_header: av_open_input_stream() failed
libavformat file format detected.
[ogg @ 0xb6952e98]cannot find sync word
LAVF_header: av_open_input_stream() failed

There is a difference between an opus stream (which is an ogg/opus stream) and raw opus data. .opus files are really .ogg files with opus data, which this package doesn't provide a way to write. It does have a reader for it (Stream type), but no writer yet (never bothered to because I haven't needed it so far, but feel free to submit a PR).

There is a difference between an opus stream (which is an ogg/opus stream) and raw opus data. .opus files are really .ogg files with opus data, which this package doesn't provide a way to write. It does have a reader for it (Stream type), but no writer yet (never bothered to because I haven't needed it so far, but feel free to submit a PR).

Originally posted by @hraban in #15 (comment)

Amplify ogg stream?

I am new to the audio streaming world, so forgive me if this is a dumb question. My application receives an Ogg stream with Opus data, but the audio is often very quiet. I'm wondering if there is a way for me to amplify each frame by, e.g., 2dB in a streaming fashion?

transfer pcm to raw opus

I tried to convert pcm to raw opus(not oggOpus) but it didn't take effect.

const sampleRate = 16000
const channels = 1 // mono; 2 for stereo
const bufferSize = 1000 // choose any buffer size you like. 1k is plenty

func main(){
	enc, err := opus.NewEncoder(sampleRate, channels, opus.AppAudio)
	if err != nil {
		panic(err)
	}
	if err != enc.SetBitrate(25600) {
		panic(err)
	}
	if err != enc.SetComplexity(10) {
		panic(err)
	}
	if err !=enc.SetMaxBandwidth(opus.Wideband){
		panic(err)
	}


        fb,err := os.Open("1549937764922.pcm")
	if err != nil {
		panic(err)
	}
	var totalOpus bytes.Buffer
	for {
		pcm := make([]int16, 320)
		err = binary.Read(fb, binary.LittleEndian, &pcm)
		if err == io.EOF || err == io.ErrUnexpectedEOF {
			break
		}
		if err != nil {
			fmt.Printf("%+v\n", err)
			break
		}
		frameSize := len(pcm)
		frameSizeMs := float32(frameSize) / channels * 1000 / sampleRate
		switch frameSizeMs { //
		case 2.5, 5, 10, 20, 40, 60:
			// Good.
		default:
			panic(fmt.Sprintf("Illegal frame size: %d bytes (%f ms)", frameSize, frameSizeMs))
		}
		data := make([]byte, bufferSize)
		n, err := enc.Encode(pcm, data)
		if err != nil {
			panic(err)
		}
		fmt.Printf("readPcm_len=%d,encodeOpus_len=%d\n",frameSize,n)
		totalOpus.Write(data[:n])
	}
	ioutil.WriteFile("encoded.opus",totalOpus.Bytes(),os.ModePerm)
}

submodules have moved

Submodules have moved so it doesn't build "out of the box" anymore.

https://github.com/xiph/opus
https://github.com/xiph/opusfile.git

Forward error correction flag in decode (decode_fec flag)

Currently, when decoding, the decode_fec flag is set to 0 in the decode function, meaning that there is no error correction in case of lost packets.
We need to be able to set it to 1.

In order to not break anything I thought either add a "DecodeWithFEC" which would be identical to "Decode" but with the flag set to 1 (same for DecodeFloat32), or having the flag on by default.

encoder: invalid argument

hello, please help me
returns the same error - opus: invalid argument
what am I doing wrong?

package main

import (
	opus "gopkg.in/hraban/opus.v2"
)

func main() {
	encoder, err := opus.NewEncoder(48000, 2, opus.AppAudio)
	if err != nil {
		println(err.Error())
		return
	}

	pcm := make([]float32, 512)

	data := make([]byte, 256)

	n, err := encoder.EncodeFloat32(pcm, data)
	if err != nil {
		println(err.Error())
		return
	}

	println(len(pcm[:n]))
}

Set encoder bitrate

There doesn't seem to be any way to set the bitrate, the complexity, the signal type (music/voice/auto), enable/disable VBR and so on.

run error

/tmp/go-build982820362/command-line-arguments/_obj/exe/main: symbol lookup error: /usr/lib/libopusfile.so.0: undefined symbol: opus_pcm_soft_clip
exit status 127

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.