Coder Social home page Coder Social logo

opus's Issues

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)
}

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

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.

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

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.

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]

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!

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)

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]))
}

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?

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

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!

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()

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

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?

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

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.

Issues with Audio Transmission in Golang WebRTC Application Using PortAudio and OPUS Encoding

Description
Hello,
I am facing issues with a Go-based WebRTC application utilizing the GO/PION library. The application is designed to capture a video stream and make it available over a WebRTC connection, while also receiving audio via WebRTC and playing it through the system speakers. I am currently implementing the final module, which involves sending audio to the WebRTC connection. The system should capture the microphone stream using github.com/gordonklaus/portaudio, encode it in OPUS using gopkg.in/hraban/opus.v2, and write it to the output track added to the WebRTC connection.

Problem
The audio is not being heard on the other end of the WebRTC connection, despite the audio track being received correctly. On the receiving end (using JavaScript and HTML), there is mostly silence with occasional brief noises occurring at regular intervals. These noises do not appear when the connection is not established, indicating that data is being sent but may be improperly encoded or not following an appropriate bitrate.

Environment

  • Golang version: 1.19
  • PION version: v4.0.0
  • PortAudio version: Latest
  • OPUS version: v2
  • Operating System: Ubuntu 20.04

Code Excerpt
import( "github.com/gordonklaus/portaudio" "github.com/hajimehoshi/oto" "github.com/pion/webrtc/v4" "github.com/pion/webrtc/v4/pkg/media" "gopkg.in/hraban/opus.v2" "github.com/pion/rtp" "log" "runtime" "time" )

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // Utilize all available CPU cores

	outboundAudioTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{
		MimeType: webrtc.MimeTypeOpus,
	}, "audio", "pion")
	if err != nil {
		log.Fatalf("Failed to create audio track: %s", err)
	}

	// Initialize PortAudio
	if err := portaudio.Initialize(); err != nil {
		log.Fatalf("Failed to initialize PortAudio: %s", err)
	}
	defer portaudio.Terminate()

	go StartMicrophoneStream(outboundAudioTrack)
}

func StartMicrophoneStream(outboundAudioTrack *webrtc.TrackLocalStaticRTP) {
	// Open default microphone device
	stream, err := portaudio.OpenDefaultStream(1, 0, sampleRate, frameSize, readAudio)
	if err != nil {
		log.Fatalf("Failed to open default stream: %s", err)
	}
	defer stream.Close()

	// Start the audio stream
	if err := stream.Start(); err != nil {
		log.Fatalf("Failed to start stream: %s", err)
	}
	defer stream.Stop()

	log.Println("Microphone streaming started")

	// Keep the stream open
	select {}
}

func readAudio(in []int16) {
	// Log input buffer
	// log.Printf("Captured audio data: %v", inputBuffer)

	// Create Opus encoder
	encoder, err := opus.NewEncoder(sampleRate, channels, opus.AppVoIP)
	if err != nil {
		log.Fatalf("Failed to create Opus encoder: %s", err)
	}

	// Encode PCM to Opus
	packet := make([]byte, 4000) // Adjust size as needed
	n, err := encoder.Encode(in, packet)
	if err != nil {
		log.Printf("Error encoding PCM to Opus: %s", err)
		return
	}

	// Log encoded packet size
	// log.Printf("Encoded audio packet size: %d", n)

	// Create RTP packet
	rtpPacket := &rtp.Packet{
		Header: rtp.Header{
			Version:        2,
			PayloadType:    111,                           // Dynamic payload type for Opus
			SequenceNumber: uint16(time.Now().UnixNano()), // Use a more appropriate sequence number generator
			Timestamp:      uint32(time.Now().UnixNano() / int64(time.Millisecond)),
			SSRC:           12345,
		},
		Payload: packet[:n],
	}

	// Marshal RTP packet to bytes
	rawPacket, err := rtpPacket.Marshal()
	if err != nil {
		log.Printf("Error marshaling RTP packet: %s", err)
		return
	}

	// Log RTP packet details
	// log.Printf("RTP packet details: %v", rtpPacket.Header)

	// Send RTP packet over WebRTC track
	if err := outboundAudioTrack.WriteRTP(rtpPacket); err != nil {
		log.Printf("Error writing RTP packet to track: %s", err)
	} else {
		log.Printf("RTP packet sent: %d bytes", len(rawPacket))
	}
}`

"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

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.