Giter Club home page Giter Club logo

oto's Introduction

Oto (v3)

Go Reference Build Status

A low-level library to play sound.

Platforms

  • Windows (no Cgo required!)
  • macOS (no Cgo required!)
  • Linux
  • FreeBSD
  • OpenBSD
  • Android
  • iOS
  • WebAssembly
  • Nintendo Switch
  • Xbox

Prerequisite

On some platforms you will need a C/C++ compiler in your path that Go can use.

  • iOS: On newer macOS versions type clang on your terminal and a dialog with installation instructions will appear if you don't have it
    • If you get an error with clang use xcode instead xcode-select --install
  • Linux and other Unix systems: Should be installed by default, but if not try GCC or Clang

macOS

Oto requires AudioToolbox.framework, but this is automatically linked.

iOS

Oto requires these frameworks:

  • AVFoundation.framework
  • AudioToolbox.framework

Add them to "Linked Frameworks and Libraries" on your Xcode project.

Linux

ALSA is required. On Ubuntu or Debian, run this command:

apt install libasound2-dev

On RedHat-based linux distributions, run:

dnf install alsa-lib-devel

In most cases this command must be run by root user or through sudo command.

FreeBSD, OpenBSD

BSD systems are not tested well. If ALSA works, Oto should work.

Usage

The two main components of Oto are a Context and Players. The context handles interactions with the OS and audio drivers, and as such there can only be one context in your program.

From a context you can create any number of different players, where each player is given an io.Reader that it reads bytes representing sounds from and plays.

Note that a single io.Reader must not be used by multiple players.

Playing sounds from memory

The following is an example of loading and playing an MP3 file:

package main

import (
    "bytes"
    "time"
    "os"

    "github.com/ebitengine/oto/v3"
    "github.com/hajimehoshi/go-mp3"
)

func main() {
    // Read the mp3 file into memory
    fileBytes, err := os.ReadFile("./my-file.mp3")
    if err != nil {
        panic("reading my-file.mp3 failed: " + err.Error())
    }

    // Convert the pure bytes into a reader object that can be used with the mp3 decoder
    fileBytesReader := bytes.NewReader(fileBytes)

    // Decode file
    decodedMp3, err := mp3.NewDecoder(fileBytesReader)
    if err != nil {
        panic("mp3.NewDecoder failed: " + err.Error())
    }

    // Prepare an Oto context (this will use your default audio device) that will
    // play all our sounds. Its configuration can't be changed later.

    op := &oto.NewContextOptions{}

    // Usually 44100 or 48000. Other values might cause distortions in Oto
    op.SampleRate = 44100

    // Number of channels (aka locations) to play sounds from. Either 1 or 2.
    // 1 is mono sound, and 2 is stereo (most speakers are stereo). 
    op.ChannelCount = 2

    // Format of the source. go-mp3's format is signed 16bit integers.
    op.Format = oto.FormatSignedInt16LE

    // Remember that you should **not** create more than one context
    otoCtx, readyChan, err := oto.NewContext(op)
    if err != nil {
        panic("oto.NewContext failed: " + err.Error())
    }
    // It might take a bit for the hardware audio devices to be ready, so we wait on the channel.
    <-readyChan

    // Create a new 'player' that will handle our sound. Paused by default.
    player := otoCtx.NewPlayer(decodedMp3)
    
    // Play starts playing the sound and returns without waiting for it (Play() is async).
    player.Play()

    // We can wait for the sound to finish playing using something like this
    for player.IsPlaying() {
        time.Sleep(time.Millisecond)
    }

    // Now that the sound finished playing, we can restart from the beginning (or go to any location in the sound) using seek
    // newPos, err := player.(io.Seeker).Seek(0, io.SeekStart)
    // if err != nil{
    //     panic("player.Seek failed: " + err.Error())
    // }
    // println("Player is now at position:", newPos)
    // player.Play()

    // If you don't want the player/sound anymore simply close
    err = player.Close()
    if err != nil {
        panic("player.Close failed: " + err.Error())
    }
}

Playing sounds by file streaming

The above example loads the entire file into memory and then plays it. This is great for smaller files but might be an issue if you are playing a long song since it would take too much memory and too long to load.

In such cases you might want to stream the file. Luckily this is very simple, just use os.Open:

package main

import (
    "os"
    "time"

    "github.com/ebitengine/oto/v3"
    "github.com/hajimehoshi/go-mp3"
)

func main() {
    // Open the file for reading. Do NOT close before you finish playing!
    file, err := os.Open("./my-file.mp3")
    if err != nil {
        panic("opening my-file.mp3 failed: " + err.Error())
    }

    // Decode file. This process is done as the file plays so it won't
    // load the whole thing into memory.
    decodedMp3, err := mp3.NewDecoder(file)
    if err != nil {
        panic("mp3.NewDecoder failed: " + err.Error())
    }

    // Rest is the same...

    // Close file only after you finish playing
    file.Close()
}

The only thing to note about streaming is that the file object must be kept alive, otherwise you might just play static.

To keep it alive not only must you be careful about when you close it, but you might need to keep a reference to the original file object alive (by for example keeping it in a struct).

Advanced usage

Players have their own internal audio data buffer, so while for example 200 bytes have been read from the io.Reader that doesn't mean they were all played from the audio device.

Data is moved from io.Reader->internal buffer->audio device, and when the internal buffer moves data to the audio device is not guaranteed, so there might be a small delay. The amount of data in the buffer can be retrieved using Player.UnplayedBufferSize().

The size of the underlying buffer of a player can also be set by type-asserting the player object:

myPlayer.(oto.BufferSizeSetter).SetBufferSize(newBufferSize)

This works because players implement a Player interface and a BufferSizeSetter interface.

Crosscompiling

Crosscompiling to macOS or Windows is as easy as setting GOOS=darwin or GOOS=windows, respectively.

To crosscompile for other platforms, make sure the libraries for the target architecture are installed, and set CGO_ENABLED=1 as Go disables Cgo on crosscompiles by default.

oto's People

Contributors

alistanis avatar bloeys avatar dianelooney avatar divverent avatar faiface avatar gucio321 avatar hajimehoshi avatar ilya33 avatar loparpanda avatar medusalix avatar neptoess avatar noofbiz avatar pankona avatar skuzzymiglet avatar tfriedel6 avatar themightygit avatar totallygamerjet avatar vsariola avatar whereswaldon avatar yuikns avatar zydeng91 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oto's Issues

Propose Logo/Icon

Hi @hajimehoshi .. I'm a graphic designer and an open source enthusiast. I would like to contribute to your project by proposing a logo/icon design for it if you allow me. I'll be doing it as a gift for free to your project.
Best regard.
Mirza Zulfan.

Add doc comments

Doc comments are empty now. When I have time, I can take care of that, if someone else doesn't do it sooner.

Automatic adjusting buffer size

Talked with @faiface .

  • Make it possible to pass the default (-1) buffer size.
  • If the context accepts the default buffer size, the context tries to adjust buffer size dynamically: if the context detects underrun during playing, it increases the buffer size.
  • From my experience, browsers require an appropriate and specific buffer size (e.g. 3200 works but power of 2 doesn't). Adjusting buffer size can consider this.

CC @Noofbiz

Any thoughts?

ignore

Steps to reproduce:

  1. Using File: aws.mp3.zip
  2. call Decode() on the file

Expected result:

The file is decoded successfully.

Actual result:

panic: runtime error: index out of range

Notes

  • ( sideInfo.big_values[gr][ch] * 2 ) > len(mainData.is[gr][ch]), so is_pos causes index out of range
  • file does not cause issues with other players
  • all aws polly mp3 streams cause same issue

Stack Trace:

panic: runtime error: index out of range

goroutine 1 [running]:
github.com/hajimehoshi/go-mp3.readHuffman(0xc4200163f0, 0xc420010308, 0xc420094000, 0xc420098000, 0xa01, 0x1, 0x0, 0x0, 0x0)
/home/.../go/src/github.com/hajimehoshi/go-mp3/read.go:177 +0x245
github.com/hajimehoshi/go-mp3.(*source).readMainL3(0xc420016360, 0x0, 0xc420010308, 0xc420094000, 0x0, 0x0, 0x0, 0x10)
/home/.../go/src/github.com/hajimehoshi/go-mp3/maindata.go:137 +0x4a4
github.com/hajimehoshi/go-mp3.(*source).readNextFrame(0xc420016360, 0x0, 0xc42000e028, 0x7f7f89d8b028, 0xc42000e028, 0x1)
/home/.../go/src/github.com/hajimehoshi/go-mp3/read.go:62 +0xfe
github.com/hajimehoshi/go-mp3.NewDecoder(0x728c00, 0xc42000e028, 0xc42000e028, 0x0, 0x0)
/home/.../go/src/github.com/hajimehoshi/go-mp3/decode.go:291 +0x119
main.run(0x0, 0x0)
/home/.../go/src/github.com/hajimehoshi/go-mp3/example/main.go:34 +0xa8
main.main()
/home/.../go/src/github.com/hajimehoshi/go-mp3/example/main.go:53 +0x22
exit status 2

Error on iOS

NSLocalizedDescription: oto: Activate: OpenAL error: code 1852797029

Write uses 100% CPU when blocking

I was just testing out the example in go-mp3 and the program is utilizing full 100% of CPU (well, 25% on a 4 core CPU). This is cause by the Write method's busy loop.

Error on ubuntu 16.04 when indirectly depending on this package.

My quick mini project is indirectly depending on this repo. I ran into an error on ubuntu but not on macOS.

My project: github.com/acmujica/ding
OS: Ubuntu 16.04 Desktop
Go version: go1.11.4 linux/amd64
Error: src/github.com/acmujica/ding/vendor/github.com/hajimehoshi/oto/player_linux.go:23:28 fatal error: also/asoundlib.h: No such file or directory compilation terminated.

Expected to happen: Compilation complete successfully when using
go get -u github.com/acmujica/ding

I just ran into this issue and will update if I figure it out later this week.

Error on macOS with Go 1.12

runtime: bad pointer in frame github.com/hajimehoshi/oto.newDriver.func1 at 0xc000065b98: 0x18
fatal error: invalid pointer found on stack

runtime stack:
runtime.throw(0x45abb42, 0x1e)
        /usr/local/go/src/runtime/panic.go:617 +0x72 fp=0x70000afd8758 sp=0x70000afd8728 pc=0x402e292
runtime.adjustpointers(0xc000065b98, 0x70000afd8858, 0x70000afd8be8, 0x48b5da0, 0x493d1e0)
        /usr/local/go/src/runtime/stack.go:591 +0x223 fp=0x70000afd87b8 sp=0x70000afd8758 pc=0x4045423
runtime.adjustframe(0x70000afd8af8, 0x70000afd8be8, 0x493d1e0)
        /usr/local/go/src/runtime/stack.go:633 +0x355 fp=0x70000afd8888 sp=0x70000afd87b8 pc=0x4045785
runtime.gentraceback(0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xc000084780, 0x0, 0x0, 0x7fffffff, 0x45c4f98, 0x70000afd8be8, 0x0, ...)
        /usr/local/go/src/runtime/traceback.go:341 +0x131b fp=0x70000afd8b60 sp=0x70000afd8888 pc=0x405203b
runtime.copystack(0xc000084780, 0x1000, 0x1)
        /usr/local/go/src/runtime/stack.go:881 +0x25e fp=0x70000afd8d18 sp=0x70000afd8b60 pc=0x4045dee
runtime.newstack()
        /usr/local/go/src/runtime/stack.go:1050 +0x2fd fp=0x70000afd8ea8 sp=0x70000afd8d18 pc=0x40461ed
runtime.morestack()
        /usr/local/go/src/runtime/asm_amd64.s:429 +0x8f fp=0x70000afd8eb0 sp=0x70000afd8ea8 pc=0x405a4ef

goroutine 35 [copystack]:
runtime.cgoCheckPointer(0x448f140, 0x18, 0x0, 0x0, 0x0)
        /usr/local/go/src/runtime/cgocall.go:409 +0x1a2 fp=0xc000065b70 sp=0xc000065b68 pc=0x40057d2                                                                                                                                      
github.com/hajimehoshi/oto.newDriver.func1(0x18, 0x18)                                                                                                                                                                                    
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/driver_openal.go:114 +0x4d fp=0xc000065bb0 sp=0xc000065b70 pc=0x436c9cd
github.com/hajimehoshi/oto.newDriver(0xac44, 0x2, 0x2, 0x2000, 0xa6001, 0xc00011ed00, 0xc00011ed20)                                                                                                                                       
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/driver_openal.go:114 +0x127 fp=0xc000065cc0 sp=0xc000065bb0 pc=0x436b2e7
github.com/hajimehoshi/oto.NewContext(0xac44, 0x2, 0x2, 0x2000, 0x0, 0x0, 0x0)                                                                                                                                                            
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/context.go:63 +0xb4 fp=0xc000065d30 sp=0xc000065cc0 pc=0x43696a4                                                                                                   
github.com/hajimehoshi/ebiten/audio.(*otoContext).ensureContext.func1()                                                                                                                                                                   
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/context.go:54 +0x76 fp=0xc000065d88 sp=0xc000065d30 pc=0x4370fb6                                                      
sync.(*Once).Do(0xc00009e228, 0xc00011edd8)                                                                                                                                                                                               
        /usr/local/go/src/sync/once.go:44 +0xb3 fp=0xc000065db8 sp=0xc000065d88 pc=0x4072823                                                                                                                                               
github.com/hajimehoshi/ebiten/audio.(*otoContext).ensureContext(0xc00009e210, 0xc0005e2000, 0x5350460)                                                                                                                                    
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/context.go:52 +0x6c fp=0xc000065e00 sp=0xc000065db8 pc=0x436f76c                                                      
github.com/hajimehoshi/ebiten/audio.(*otoPlayer).ensurePlayer(0xc0049a2740, 0xc004016000, 0x800)                                                                                                                                          
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/context.go:85 +0x32 fp=0xc000065e38 sp=0xc000065e00 pc=0x436f912                                                      
github.com/hajimehoshi/ebiten/audio.(*otoPlayer).Write(0xc0049a2740, 0xc004016000, 0x800, 0x800, 0x800, 0x0, 0x0)                                                                                                                         
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/context.go:71 +0x2f fp=0xc000065e80 sp=0xc000065e38 pc=0x436f7cf                                                      
io.copyBuffer(0xc689ae8, 0xc0049a2740, 0x463cd20, 0xc0049a2760, 0xc004016000, 0x800, 0x800, 0x4517020, 0x0, 0xc689ae8)                                                                                                                    
        /usr/local/go/src/io/io.go:404 +0x1fb fp=0xc000065ef8 sp=0xc000065e80 pc=0x4096a1b                                                                                                                                                 
io.Copy(...)                                                                                                                                                                                                                              
        /usr/local/go/src/io/io.go:364                                                                                                                                                                                                     
io.CopyN(0xc689ae8, 0xc0049a2740, 0x463c400, 0xc0000a60a0, 0x800, 0x0, 0x0, 0x0)                                                                                                                                                          
        /usr/local/go/src/io/io.go:340 +0x9c fp=0xc000065f58 sp=0xc000065ef8 pc=0x409677c                                                                                                                                                  
github.com/hajimehoshi/ebiten/audio.(*Context).loop(0xc0000c2140)                                                                                                                                                                         
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/audio.go:155 +0x27d fp=0xc000065fd8 sp=0xc000065f58 pc=0x436d2bd                                                      
runtime.goexit()                                                                                                                                                                                                                          
        /usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc000065fe0 sp=0xc000065fd8 pc=0x405c451                                                                                                                                       
created by github.com/hajimehoshi/ebiten/audio.NewContext                                                                                                                                                                                 
        /Users/hajimehoshi/go/pkg/mod/github.com/hajimehoshi/[email protected]/audio/audio.go:103 +0x16d 

.5x speed on Windows

I tested github.com/hajimehoshi/go-mp3/example/main.go, and found .5x speed. In the first place, I began to doubt the current usage of waveOut* functions is correct.

how stop playing?

Hello. I can play any music, but i understand how stop it? Maybe, player.stop() ?

oto: waveOutOpen error: MMSYSERR_NOMEM

In the windows system, the mp3 file is played every second, and the error is given when the time is long. What could be the cause, how can I solve this problem?

oto: waveOutOpen error: MMSYSERR_NOMEM

Crash on Windows with Go 1.12

This depends on GC timing. At waveOutOpen, the argument f is a pointer of a struct and the struct might be GCed before finishing waveOutOpen.

runtime.KeepAlive fixes this.

cannot convert nil to type _Ctype_jobject

When I'm trying to build for android I'm getting the following errors since updating to go 1.11:

# github.com/hajimehoshi/oto
../../../hajimehoshi/oto/player_android.go:205:31: cannot convert nil to type _Ctype_jobject
../../../hajimehoshi/oto/player_android.go:280:18: cannot convert nil to type _Ctype_jobject
../../../hajimehoshi/oto/player_android.go:293:15: cannot use nil as type _Ctype_jobject in assignment

Could be due to the changes to the changes to the way cog interacts with the jobject hierarchy in Java's JNI interface.

From the release notes (this is for 1.10 but then they were warnings now they're errors):

"These types must be uintptr on the Go side because they would otherwise confuse the Go garbage collector; they are sometimes not really pointers but data structures encoded in a pointer-sized integer. Pointers to Go memory must not be stored in these uintptr values.

Because of this change, values of the affected types need to be zero-initialized with the constant 0 instead of the constant nil. Go 1.10 provides gofix modules to help with that rewrite:

go tool fix -r cftype
go tool fix -r jni

Sound is chopped on background tabs

Oto uses time.Sleep, which is implemented by setTimeout. Such functions are throttled on background tabs on some browsers and audio are uglily chopped.

Oto test coverage

Headless testing of such a low level library might be impossible, or take a lot of work to get started. I'd like to explore getting some test coverage for oto.
The biggest roadblock is testing the drivers without any actual sound cards available. There's a couple ways we could go about doing this. In the test, we could replace theContext's driverWriter with something like the following

// stepPlayer is used for headless mode audio, such as for tests
// you can control exactly how many steps it takes which allows for verification
// of the PCM data written to it.
type stepPlayer struct {
	ThrowWriteError bool
	stepStart       chan []byte
	stepDone        chan struct{}
}

func (l *stepPlayer) Write(b []byte) (int, error) {
	if l.ThrowWriteError {
		return 0, errors.New("write error")
	}
	l.stepStart <- b
	<-l.stepDone

	return len(b), nil
}

func (l *stepPlayer) Close() error {
	return nil
}

func (l *stepPlayer) Bytes() []byte {
	return <-l.stepStart
}

func (l *stepPlayer) Step() {
	if len(l.stepDone) > 0 {
		return
	}
	l.stepDone <- struct{}{}
}

(this is what I replaced oto.Player with in engo to test it. All it does is take in the PCM data sent to the player and spit it back out.) This lets the tests check that data is actually being passed, and the tests can compare that data to what it expects. The upside is it should work, with build tags. The downside is that it wouldn't actually test any of the actual drivers, only the mock test driver would actually ever be tested. So coverage would be less than 100%.

Another alternative would be to create/use dummy drivers for testing. For example, ALSA has a loopback driver here. If it could be setup on Travis, then this driver would take in data and spit it out, similar to above. This would have the added benefit of actually testing the driver code, so coverage could get to 100% (or at least pretty good!) There's also a node.js package here. Not sure about windows/ios/mobile testing. I'll look around and see.

how can I change another mp3 to play

`
package main

import (
"io/ioutil"
"time"
"github.com/hajimehoshi/oto"
"github.com/tosone/minimp3"
"log"
)

func players() error {
file, _ := ioutil.ReadFile("assets/mp3/test.mp3")
dec, data, _ := minimp3.DecodeFull(file)

player, _ := oto.NewPlayer(dec.SampleRate, dec.Channels, 2, 4000)
player.Write(data)

dec.Close()
player.Close()
return nil

}

func main() {
for i := 0; i < 3; i++ {
if err := players(); err != nil {
log.Fatal(err)
}
time.Sleep(time.Second * 5)
}
}`

when I run above code it got a error:
panic: oto: NewContext can be called only once

record audio

here is a way to record audi for windows using the same dll sycall you use.
I also need to record audio on other OS's. Do you think that the same approach can be used for them ?

// Record Windows Audio project main.go
package main

import (
	"fmt"
	"log"
	"syscall"
	"time"
	"unsafe"
)

var (
	winmm         = syscall.MustLoadDLL("winmm.dll")
	mciSendString = winmm.MustFindProc("mciSendStringW")
)

func MCIWorker(lpstrCommand string, lpstrReturnString string, uReturnLength int, hwndCallback int) uintptr {
	i, _, _ := mciSendString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpstrCommand))),
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpstrReturnString))),
		uintptr(uReturnLength), uintptr(hwndCallback))
	return i
}

func main() {
	fmt.Println("winmm.dll Record Audio to .wav file")

	i := MCIWorker("open new type waveaudio alias capture", "", 0, 0)
	if i != 0 {
		log.Fatal("Error Code A: ", i)
	}

	i = MCIWorker("record capture", "", 0, 0)
	if i != 0 {
		log.Fatal("Error Code B: ", i)
	}

	fmt.Println("Listening...")

	time.Sleep(10 * time.Second)

	i = MCIWorker("save capture mic.wav", "", 0, 0)
	if i != 0 {
		log.Fatal("Error Code C: ", i)
	}

	i = MCIWorker("close capture", "", 0, 0)
	if i != 0 {
		log.Fatal("Error Code D: ", i)
	}

	fmt.Println("Audio saved to mic.wav")
}

Error compiling the example on windows

I am still a noob when it comes to golang. Sorry in advance, if this is a stupid mistake. I am working with Windows 7 and go version go1.12 windows/amd64

I tried to work with beep from faiface but i always get the same error (even the example from oto):

D:\ (bla bla bla)  \go_workspace\src\github.com\hajimehoshi\oto\example>go build main.go
# github.com/hajimehoshi/oto
..\winmm_windows.go:109:11: undefined: "golang.org/x/sys/windows".Errno

error in cgo part of driver_linux.go while cross compiling the example project for linux on arm64 architecture

Hello together,
i have a problem compiling the project for linux on a arm64 platform.
What i figured out so far:
When you want to cross compile something in go that uses cgo you have to enable the cgo cross compiling, which i did as fallowed: CGO_ENABLED=1
Also you have to specify the OS and the architecture, which i did as followed: GOOS="linux" GOARCH="arm64"
Then you have to pic a cross compiler. I choosed gcc-aarch64-linux-gnu. To use this cross compiler you have to install the fallowing packages:
apt-get install gcc-aarch64-linux-gnu
apt-get install cpp-aarch64-linux-gnu
apt-get install g++-aarch64-linux-gnu
to take this compilerfor building, you have to insert this command in the build command:
CC=aarch64-linux-gnu-gcc
The final Build command looks like this:
GOOS="linux" GOARCH="arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build -a -o /home/matthias/go/src/github.com/hajimehoshi/oto/playersound /home/matthias/go/src/github.com/hajimehoshi/oto

The compilation starts but then i get a error in driver_linux on line 22 this is the Error message:
/usr/lib/gcc-cross/aarch64-linux-gnu/5/../../../../aarch64-linux-gnu/bin/ld: cannot find -lasound

this is strange because i definitely have installed libasound2-dev as well and i can find the needed asound.h in the fallowing paths:
/usr/include/sound
/usr/src/linux-headers-4.15.0-44/include/sound
/usr/src/linux-headers-4.15.0-45/include/sound
/usr/src/linux-headers-4.15.0-44/include/uapi/sound
/usr/src/linux-headers-4.15.0-45/include/uapi/sound
/usr/src/linux-headers-4.15.0-44/include/uapi/linux
/usr/src/linux-headers-4.15.0-45/include/uapi/linux

I have no idea at all, what could be the problem here, does anyone have an idea?
PS: The normal compilation (without cross compiler) works without any problem
greetings Matthias

Oto and RPi

Hello, I was wondering if you had any experience in deploying oto on an rpi. I tried cross compiling the library, without success.

Any insight would be helpful.
thank you for your time.

Add prerequisite for alsa/asoundlib.h in README.md

It's quite basic, but there's some Linux idiots just like me ;)
So it would be great if README.md mentions that how to get alsa/asoundlib.h.
Like this:

Prerequisite

  • Ubuntu/Debian
sudo apt update -y && apt install -y libasound2-dev

Set limitation to cache in `Player` for syncing

As far as I can tell, currently it's possible to play audio, but there's no way to tell how much of it has already been processed, which makes it hard to time-synchronize audio playback.

I'm not sure about the concrete API, that needs to be figured out.

Cannot Cross Compile For Linux

Hello

I have been using oto on a project of mine and it has been working great. I'm now wanting to cross compile the application for linux, built on my mac. However, I'm getting the following error:

./player.go:25:18: undefined: player

Building for OSX and cross compiling for windows works fine.

Nathans-MacBook-Air:oto nstehr$ go version
go version go1.9.2 darwin/amd64
Nathans-MacBook-Air:oto nstehr$ go build
Nathans-MacBook-Air:oto nstehr$ GOOS=windows go build
Nathans-MacBook-Air:oto nstehr$ GOOS=linux go build
# _/Users/nstehr/oto
./player.go:25:18: undefined: player

Version of oto library: commit 029232d8b473a85bc966df7706341c3592c632a6

Allow only one instance of Player or multiple instances

I realized that multiple Player instances might causes problems in the current implementation (e.g. #46). I'm still investigating this, but at least the fact is I've not considered multiple instances.

To solve this problem, there are 2 suggestions:

  1. Allow only one Player instance. This is simple, but users would need to mixing if they want to play multiple sources (actually I do this in Ebiten).

  2. Allow multiple Player instances. Oto does multiplexing sources.

I'm leaning toward 2. since it wouldn't break existing usages. Any thoughts? CC @faiface @Noofbiz

shortage of AudioTrack on Android

Hi @hajimehoshi !

On android, I faced problem to playback audio.
Audio playback does work at launching application, but some times after, audio playback doesn't work at all. I investigated and found that this problem seems to be caused by shortage of AudioTrack.

Around this part, AudioTrack is allocated and it is registered to GlobalRef in JNI.
https://github.com/hajimehoshi/oto/blob/8ab1cc50f21ad05f93bf99dc8c44d6aa101c29c9/player_android.go#L104-L113

I think AudioTracks should be released after their use, and also be deleted from GlobalRef.
It seems there's number limitation for allocatiing AudioTracks, they can be available in same time on Android (about 30?, sorry I couldn't find out specification.).

So my application playbacks audio again and again and again for sound effects, I noticed such issue.
I found this problem with application that is generated by gomobile build.

(If you don't mind, I will create a pull request and I'd like you to check my modification to fix this problem.)

linux compile 32-bit error

Hi:
I use go build and it's work well.
When I use GOARCH=386 CGO_ENABLED=1 go build,It's return an error like this


1 errors occurred:
--> linux/386 error: exit status 2
Stderr: # voice/vendor/github.com/hajimehoshi/oto
/usr/bin/ld: 找不到 -lasound
collect2: error: ld returned 1 exit status

How can I solve it?

Player doesn't satisfy io.Writer's requirements

https://golang.org/pkg/io/#Writer

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-nil error if it returns n < len(p). Write must not modify the slice data, even temporarily.

So Write must process all given data at one time as long as errors don't occur. Now Player's Write might return without processing all given data.

Fix error messages

There are still some error messages using Proceed, which is an old name for Write.

js: Hard to determine appropriate buffer size for Chrome

It is now really hard to determine an appropriate buffer size for Chrome. I found 12800 [bytes] worked with 44100 [Hz] and 48000 [Hz], but doesn't work with other sample rate like 32000 [Hz] or 96000 [Hz]. I couldn't see the rule.

Instead of using AudioBuffer, I suggest to use ScriptProcessorNode that can have a callback for PCM. Unfortunately ScriptProcessorNode is deprecated and will be replaced with AudioWorklet in the future, but not all major browsers support AudioWorklet.

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.