Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
0
Members

[solved] Advanced audio functions? Locked

A topic by Doomcaster created Jan 15, 2016 Views: 845 Replies: 4
This topic was locked by Elisée Jan 17, 2016
Viewing posts 1 to 3
(6 edits)

I usually don't need access to anything besides basic audio functions (play, stop, volume, etc), but I recently thought of a game concept that would work best if I could synchronize it to the music being played. The only things that I could think of that could accomplish this, would be to access some sort of buffer before it plays, or be able to get the current position of the song and read data from the file itself.

It looks like JavaScript has something called Web Audio, which might be what I'm looking for (but also way more complicated than Sup.Audio). Is there some way to access this API since Typescript is a superset of JavaScript? Or is there some other API that would work better? (I peeked at the source code for Sup.Audio.SoundPlayer, and it looks like this might be what it runs off of)

So basically, I'd like to know...

  • If there's a way to access the audio buffer.
  • If the file data from audio assets can be accessed with code.
  • If the song position can be retrieved.
  • If sound files can be loaded from URLs.
  • If something like Web Audio (JavaScript) can be used in TypeScript.

After looking at some articles on rhythm games, I found this. It sounds like I'd need to scan through all the sound data and calculate the average volume energy, then calculate the current energy level from the song position. Seems like this sort of game is much more complicated than I had originally thought, haha. I think getting audio data from the file may be impossible now that I've thought about it. It'd be encrypted by it's file format, so I'll just cross that out in my original post. That leaves me with the buffer.

The thing is, I don't know if the buffer contains all of the sound data, or just the data about to be played. I assumed the buffer contained a large string of numbers that represents the frequencies and volume of the entire song. What I plan on doing is grabbing large pieces of that data and processing it. The only thing I really need now is a way to access that data, and from there I can make a bunch of messy code to see what happens :p

Any ideas?

Moderator(+1)
(I peeked at the source code for Sup.Audio.SoundPlayer, and it looks like this might be what it runs off of)

Yes, Sup.Audio uses WebAudio behind the scenes. As we tend to do with many things in Superpowers Game, we've wrapped it into an API that's more convenient and simpler for most games, but advanced features haven't been exposed yet.

You can access WebAudio from a Superpowers Game project. In JavaScript, "window" is the global object. So, any objects defined in the Web Audio docs can be access as window.NameOfThatObject, you just need to declare that window exists first, so TypeScript won't complain:

declare var window;
// window.AudioBuffer is now available

Alternatively, you can install Florent Poujol's DOM plugin which defines all Web APIs in a typed fashion to your Superpowers Game. Then you can access AudioBuffer directly.

If you want to plug into Superpowers's Sup.Audio's internal Web Audio context, you might go through the internal game instance:

// Start by accessing an inner Actor object
// It is not declared in our TypeScript APIs so you need to cast to any first:
let innerActor = (Sup.getActor("Some actor") as any).__inner;

// You can then gain access to the game instance (the Superpowers Game's engine main object)
let gameInstance = innerActor.gameInstance;

// Assuming you have installed the DOM plugin, you can use AudioContext as a type:
let audioCtx: AudioContext = gameInstance.audio.getContext();
let masterGain: GainNode = gameInstance.audio.masterGain;

Now you can do your own things with custom buffers etc.

Another approach, probably much simpler actually, would be to go through a Sup.Audio.SoundPlayer:

let soundPlayer = Sup.Audio.playSound("My Asset");
let innerSoundPlayer = (soundPlayer as any).__inner;

// innerSoundPlayer.audioCtx is the audio context
// innerSoundPlayer.audioMasterGain is the master gain node // innerSoundPlayer.buffer contains the AudioBuffer // etc. See https://github.com/superpowers/superpowers-game/blob/master/SupEngine/src/SoundPlayer.ts

Hope that helps!

Thanks for all the info! :D

(1 edit) (+1)

Using the SoundPlayer method, I was able to extend the class as SoundPlayerAdvanced, and add a Buffer interface to get auto-completion. I used Sup.log to test it, and I was able to get an array of data from the channels, along with the duration, length, and sampleRate of the buffer.

interface Buffer {
    sampleRate: number;
    length: number;
    duration: number;
    numberOfChannels: number;
    getChannelData(number);
    copyFromChannel(number);
    copyToChannel(number);
}

class SoundPlayerAdvanced extends Sup.Audio.SoundPlayer {
    buffer: Buffer;
    constructor(pathOrAsset: string|Sup.Sound, volume?: number, options?: {loop?: boolean, pitch?: number, pan?: number}) {
        super(pathOrAsset, volume, options);
        this.buffer = (this as any).__inner.buffer;
    }
}

Thanks again! :D