audio

package module
v0.0.0-...-f5c4f25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2019 License: BSD-2-Clause Imports: 9 Imported by: 0

README

TGE-AUDIO - Audio plugin for TGE

Godoc Go Report Card

Audio support for TGE runtime - TGE

Based on :

  • gomobile exp/audio/al - Copyright (c) 2009 The Go Authors. All rights reserved.
  • OpenAL - Copyright (C) 1991 Free Software Foundation, Inc.

The Audio API is based on WebAudio API specifications ported to OpenAL for Desktop and Mobile targets.

Targets

  • Desktop (Work In Progress)
  • Mobile (Work In Progress)
  • Browser

Dependencies

Desktop & Mobile

In order to use this package on Linux desktop distros, you may need OpenAL library as an external dependency:

sudo apt-get install libopenal-dev

Limitations

Only Vorbis format (.ogg) is currently supported for audio files, MP3 will be eventually supported in future releases.

Only StereoPannerNode and GainNode are currently available, additional and custom AudioNodes and spacialization features are planned in future releases.

Audio can't be started without user interaction on browsers, see details in implementation.

Implementation

The WebAudio API offers a complete and comprehensive approach to audio implementation in 2D/3D scenes, tge-audio tries to benefit from it by exposing also OpenAL the same way.

See example at AUDIO examples

package main

import (
	"fmt"
	"time"

	tge "github.com/thommil/tge"
	audio "github.com/thommil/tge-audio"
)

type AudioApp struct {
	runtime                tge.Runtime
	audioInit              bool
	sampleBuffer           audio.Buffer
	stereoPanNode          audio.StereoPannerNode
	gainNode               audio.GainNode
	destinationNode        audio.DestinationNode
	mediaElementSourceNode audio.MediaElementSourceNode
	width                  int32
	height                 int32
}

func (app *AudioApp) OnCreate(settings *tge.Settings) error {
	fmt.Println("OnCreate()")
	settings.Fullscreen = true
	return nil
}

func (app *AudioApp) OnStart(runtime tge.Runtime) error {
	fmt.Println("OnStart()")
	app.runtime = runtime

	runtime.Subscribe(tge.MouseEvent{}.Channel(), app.OnMouseEvent)
	runtime.Subscribe(tge.ResizeEvent{}.Channel(), app.OnResize)
	return nil
}

// InitAudio is start on mouse click only due to browsers restrictions
func (app *AudioApp) InitAudio() error {
	var err error

	//Buffer (should be done in a loading screen off course)
	fmt.Println("Loading left-right.ogg in buffer")
	if app.sampleBuffer, err = audio.CreateBuffer("left-right.ogg"); err != nil {
		return err
	}

	// Audio graph
	fmt.Println("Creating audio graph")
	if app.destinationNode, err = audio.CreateDestinationNode(); err != nil {
		return err
	}
	if app.gainNode, err = audio.CreateGainNode(); err != nil {
		return err
	}
	if app.stereoPanNode, err = audio.CreateStereoPannerNode(); err != nil {
		return err
	}

	app.stereoPanNode.Connect(app.gainNode).Connect(app.destinationNode)

	//Music (should be done in a loading screen off course)
	fmt.Println("Loading music.ogg in media element")
	if app.mediaElementSourceNode, err = audio.CreateMediaElementSourceNode("music.ogg"); err != nil {
		return err
	}

	var mediaElementGainNode audio.GainNode
	if mediaElementGainNode, err = audio.CreateGainNode(); err != nil {
		return err
	}
	mediaElementGainNode.Gain(0.3)
	app.mediaElementSourceNode.Connect(mediaElementGainNode).Connect(app.destinationNode)

	fmt.Println("Start playing music")
	app.mediaElementSourceNode.Play(true)

	app.audioInit = true

	return nil
}

func (app *AudioApp) OnResume() {
	fmt.Println("OnResume()")
	// Open sound
	if app.audioInit {
		app.gainNode.Connect(app.destinationNode)
		app.mediaElementSourceNode.Play(true)
	}
}

func (app *AudioApp) OnResize(event tge.Event) bool {
	app.width = (event.(tge.ResizeEvent)).Width
	app.height = (event.(tge.ResizeEvent)).Height
	return false
}

func (app *AudioApp) OnMouseEvent(event tge.Event) bool {
	mouseEvent := event.(tge.MouseEvent)
	if mouseEvent.Type == tge.TypeDown && (mouseEvent.Button&tge.ButtonLeftOrTouchFirst != 0) {
		if !app.audioInit {
			if err := app.InitAudio(); err != nil {
				fmt.Printf("ERROR: %s\n", err)
			}
		}

		app.stereoPanNode.Pan(float32(mouseEvent.X)/float32(app.width)*2 - 1.0)
		app.gainNode.Gain(float32(app.height-mouseEvent.Y) / float32(app.height))

		fmt.Printf("Set pan to %v and gain to %v%%\n", (float32(mouseEvent.X)/float32(app.width)*2 - 1.0), float32(app.height-mouseEvent.Y)/float32(app.height)*100)

		if sourceNode, err := audio.CreateBufferSourceNode(app.sampleBuffer); err != nil {
			fmt.Printf("ERROR: %s\n", err)
		} else {
			sourceNode.Connect(app.stereoPanNode)
			if mouseEvent.X < app.width/2 {
				// Left chunk
				sourceNode.Start(0, 0, 0.5, false, 0, 0)
			} else {
				// Right chunk
				sourceNode.Start(0, 0.5, 0.5, false, 0, 0)
			}
		}
	}
	return false
}

func (app *AudioApp) OnRender(elaspedTime time.Duration, syncChan <-chan interface{}) {
	<-syncChan
}

func (app *AudioApp) OnTick(elaspedTime time.Duration, syncChan chan<- interface{}) {
	syncChan <- true
}

func (app *AudioApp) OnPause() {
	fmt.Println("OnPause()")
	// Close sound
	if app.audioInit {
		app.gainNode.Disconnect(app.destinationNode)
		app.mediaElementSourceNode.Pause()
	}
}

func (app *AudioApp) OnStop() {
	fmt.Println("OnStop()")
	app.runtime.Unsubscribe(tge.MouseEvent{}.Channel(), app.OnMouseEvent)
	app.runtime.Unsubscribe(tge.ResizeEvent{}.Channel(), app.OnResize)
}

func (app *AudioApp) OnDispose() {
	fmt.Println("OnDispose()")
}

func main() {
	tge.Run(&AudioApp{})
}

Documentation

Index

Constants

View Source
const Name = "audio"

Name name of the plugin

Variables

This section is empty.

Functions

This section is empty.

Types

type Buffer

type Buffer interface {
	// Delete the buffer and free associated memory
	Delete()
}

Buffer interface represents a short audio asset residing in memory, created from an audio file See https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer

func CreateBuffer

func CreateBuffer(path string) (Buffer, error)

CreateBuffer creates a Buffer from an assets path (supports: OGG only)

type BufferSourceNode

type BufferSourceNode interface {
	Node
	// Start playing node with given settings :
	//	- delay before playing in seconds, 0 to start immediatly
	//	- offset in seconds in buffer, 0 to start from beginning
	//	- duration of the sample to play in seconds, 0 to play to end
	//	- loop indicates to play in loops
	//	- loopStart if loop is set is the offset in seconds of the loop (0 for beginning)
	//	- loopEnd if loop is set is the end of the loop in seconds (0 to play to end)
	//
	//	... so to just play the sample :
	//	 Start(0, 0, 0, false, 0, 0)
	Start(delay, offset, duration float32, loop bool, loopStart, loopEnd float32)
	// Stop playing node
	Stop()
}

BufferSourceNode interface represents an audio source consisting of in-memory audio data, stored in an AudioBuffer See https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode

func CreateBufferSourceNode

func CreateBufferSourceNode(buffer Buffer) (BufferSourceNode, error)

CreateBufferSourceNode creates a new BufferSourceNode, this method must be called each time you want to play a BufferSourceNode

type DestinationNode

type DestinationNode interface {
	Node
}

DestinationNode interface represents the end destination of an audio graph in a given context — usually the speakers of your device See https://developer.mozilla.org/en-US/docs/Web/API/AudioDestinationNode

func CreateDestinationNode

func CreateDestinationNode() (DestinationNode, error)

CreateDestinationNode creates a new DestinationNode to connect audio graph output

type GainNode

type GainNode interface {
	Node
	// Gain changes the output volume from 0 silence to 1 full
	Gain(value float32)
}

GainNode interface represents a change in volume See https://developer.mozilla.org/en-US/docs/Web/API/GainNode

func CreateGainNode

func CreateGainNode() (GainNode, error)

CreateGainNode creates a new GainNode to connect in audio graph

type MediaElementSourceNode

type MediaElementSourceNode interface {
	Node
	// Play the attached media with loop option
	Play(loop bool)
	// Pause the attached media
	Pause()
	// Delete node and free associated memory
	Delete()
}

MediaElementSourceNode interface represents an external audio source for continuous play (music) See https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode

func CreateMediaElementSourceNode

func CreateMediaElementSourceNode(path string) (MediaElementSourceNode, error)

CreateMediaElementSourceNode creates a new MediaElementSourceNode from an assets path (supports: OGG only)

type Node

type Node interface {
	// Connect the node output to given node
	Connect(node Node) Node
	// Disconnect the node output from the given node
	Disconnect(node Node)
}

Node interface is a generic interface for representing an audio processing module. See https://developer.mozilla.org/en-US/docs/Web/API/AudioNode

func CreateNode

func CreateNode() (Node, error)

CreateNode creates a new custom node, not implemented yet

type StereoPannerNode

type StereoPannerNode interface {
	Node
	// Pan the output from -1 left to 1 right
	Pan(value float32)
}

StereoPannerNode interface represents a simple stereo panner node that can be used to pan an audio stream left or right See https://developer.mozilla.org/en-US/docs/Web/API/StereoPannerNode

func CreateStereoPannerNode

func CreateStereoPannerNode() (StereoPannerNode, error)

CreateStereoPannerNode creates a new StereoPannerNode to connect in audio graph

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL