WebAudio - separate audio channels - html

I have 2 separate audio files, that will play through the WebAudio API.
One contains background music and will always be on.
The other contains speech, and my graphics will react to the pitch of the sound. I have a working bit of code that uses the WebAudio.context together with an analyserNode and a dynamicNode to figure out the pitch of the currently playing sound file.
function init() {
this.context = ((Object)(createjs.WebAudioPlugin)).context;
this.analyserNode = this.context.createAnalyser();
this.analyserNode.fftSize = 32;
this.analyserNode.smoothingTimeConstant = 0.7;
this.analyserNode.connect(this.context.destination);
this.dynamicsNode = ((Object)(createjs.WebAudioPlugin)).dynamicsCompressorNode;
this.dynamicsNode.disconnect();
this.dynamicsNode.connect(this.analyserNode);
this.freqFloatData = new Float32Array(this.analyserNode.frequencyBinCount);
this.freqByteData = new Uint8Array(this.analyserNode.frequencyBinCount);
}
function onUpdate() {
this.analyserNode.getByteFrequencyData(this.freqByteData);
// ---- do stuff with this.freqByteData[0]; ---- \\
}
However, when i play the background music and the speech file simultaneously, i can only retrieve the pitch of both sounds as one.
Is it possible, through the WebAudio API, to get the pitch from a single sound file, while multiple are playing?

If you mean "can I apply equalization only to the music tracks, and have the speech sounds unaffected" the answer is yes, definitely - equalization (and other filtering) is an inline effect, it doesn't need to be applied globally. If you mean "I have source material with speech and music mixed, can I separate them" then Ken's right, that's a much harder challenge.

Related

How to know if a music file has finished playing?

In cocos2d-x, you can play music by doing the following:
auto audio = SimpleAudioEngine::getInstance();
// set the background music and play it just once.
audio->playBackgroundMusic("mymusic.mp3", false);
But how do we know if the music has finished playing ? The game could be interrupted by a phone call (triggering other code that pauses the game and the music) or paused by the user.
Is there anyway to know if the file has finished playing ? I know we can keep some kind of timer to keep track of the duration the song has been playing but that seems hacky, and this is a common use case, especially if we want to queue a playlist.
It looks like you'll have to test audio->isBackgroundMusicPlaying() in your update() methods.
There ought to be a delegate, or some other kind of callback, which will tell you such things. I guess you could subclass SimpleAudioEngine to add this.
EDIT There is experimental::AudioEngine which offers a didFinishCallback:
static void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback);
However you need to be aware that I don't think it supports all platforms, so use with caution.

What should i use to load audio in as3 instead of load()?

I have a setup of 4x4 drum pads which are essentially buttons or movie clips with 3 states to show visual feedback (like the lighting up of the pads when they are pressed). I have tested this setup on an android tablet as well as a windows 7 touch-enabled laptop. Obviously the windows 7 laptop is more powerful and thus more responsive.
But not responsive enough.
I am wondering how I should be approaching the loading of audio files which are short drum-kit sample sounds in mp3 format stored in an assets folder next to the swf file.
Is there a better way, such as a way to cache the sounds so that I don't have to reload them each time the sound event is triggered?
Any help on this is greatly appreciated. (I just am not aware of how else, right now, to approach loading sounds other than calling a new sound each time the pad is pressed, thus not really caching the sound)
var kickc_03:Sound=new kickc_03_mp3(); // not sure whether to use Sound() or kickc_03 here..
// or
var kickc_03:kickc_03_mp3=new kickc_03_mp3();
// they will both work because kickc_03_mp3 subclasses Sound.
if i were you i would do something like:
// execute this once
var drumNum:int = 16;
var soundArray:Array = [null];
var C:Class;
init();
function init():void{
for(var i:int=1;i<=drumNum;i++){
C = Class(getDefinitionByName("kickc_"+formatF(i)+"_mp3");
soundArray.push(new C());
}
function formatF(n:int):String{
var s:String=n.toString();
while(s.length<2){
s="0"+s;
}
return s;
}
//////////////////////////////////////////////
now anytime you want to generate a kickc_somenum_mp3 sound, use:
soundArray[somenum].play();

How call volume slider function in different keyFrames with different sound channels?

I have this code for my volume slider:
var stVolume:SoundTransform=new SoundTransform();
slider.addEventListener(SliderEvent.CHANGE,volslider);
function volslider(ev:SliderEvent):void
{
stVolume.volume=(ev.value/100);
sch1.soundTransform = stVolume;
}
I have many frames with different sound channels. How can I call this function with specific sound channels in each frame like shc2, sch3 and others instead use repeatedly all of function?
Is it possible send SoundChannel name whit eventListener for example:
slider.addEventListener(SliderEvent.CHANGE,volslider(/*something i don't know*/,sch10));
An AudioSource is attached to a GameObject for playing back sounds in a 3D environment. In order to play 3D sounds you also need to have a AudioListener. The audio listener is normally attached to the camera you want to use. Whether sounds are played in 3D or 2D is determined by AudioImporter settings.

Split screen in Actionscript 3

I'm trying to make a pure AS3 game, and need a way to split the screen so that two players can have individual "cameras" that follow the around the game world. The problem is that a sprite can't have multiple parents. I'm trying to hack my way around this problem by having classes that duplicate sprites and manage all of their updates, but I'm not getting very far and my code is getting very, very ugly.
Does anyone know a good workaround or method for doing this? I can't seem to find much on-line on the subject.
I think you should use BitmapData copyPixels method
.copyPixels(point_0, rectangle_0)---> FirstPlayerScreen
World.Bitmap -
.copyPixels(point_0, rectangle_0)---> SecondPlayerScreen
Thanks for everyone's suggestions. What I've ended up with is a World class that I can add regular Sprite objects to as children. The World object manages and updates copies of those sprites, and world.getCamera() can be called as many times as necessary to display custom copies of the game world.
The key part is making copies of the sprites, this is the function I wrote to do that:
public function bitmapCopy(original:DisplayObject):Sprite
{
var returnSprite:Sprite = new Sprite();
if (original.width == 0 || original.height == 0) return returnSprite
var x = original.x; var y = original.y
var rotation = original.rotation
original.x = 0; original.y = 0; original.rotation = 0
var bounds:Rectangle = original.getBounds(original.parent)
var m:Matrix = new Matrix()
m.tx = -bounds.x
m.ty = -bounds.y
var bitmapData:BitmapData = new BitmapData( bounds.width, bounds.height, true,
0xFF0000 );
bitmapData.draw(original, m);
var bitmap:Bitmap = new Bitmap( bitmapData );
bitmap.x = bounds.x
bitmap.y = bounds.y
returnSprite.addChild(bitmap);
returnSprite.x = original.x = position.x
returnSprite.y = original.y = position.y
returnSprite.rotation = original.rotation = rotation
return returnSprite;
}
The returned Sprite can be added to the stage and will act in exactly the same way as the original (except for being static, of course). Hopefully this should help anyone else who comes across this problem.
Your theory is on the right track - you're probably just stumbling over your implementation. Organization and keeping things object-oriented will be your best friend in this scenario.
It's hard to give you a good example based off of a limited description of your game, but in general, I'd have a Screen class that can be instantiated multiple times, and I'd keep track of each instantiation (that gives us our multiple "players"). Each Screen has a stage, and you're building your game world on that stage.
The key here is data organization and good communication. Remember, there's only one "world", and you're just showing multiple instances of it. So you'll want a central Model to store data about every object in your singular game world. That Model will drive the rendering of that world to your multiple screens. If a player changes an object on their screen (let's say they move it), then you'll update the Model with that object's new location. Then, you'll broadcast those new coordinates to each Screen instance, so that all of your screens will update.
How you "broadcast" this can vary (and depends largely on the real-time nature of your game). If your game is very real-time and you're running a game loop, then you may just want to pass the objects' data along in every loop, and they'd update that way. If your game isn't as dependent of being real-time, then you can set up event listeners or a custom notification system that'll alert all of the instances of an object to update itself.
I know this is very high-level, but it's hard to give an in-depth answer without more info about your game. Hopefully this helps point you in the right direction - what you're attempting is definitely not simple, so don't get discouraged!
If you develop your game using MVC architecture principles then it should be trivial to draw your game twice, each player having an instance of the game's "view" but positioned according to a different character. If you give a layer mask to each instance then you could put the two instances side by side and so create a split screen effect.
Happy coding!
I'm working on a split screen myself just now:
masking to draw 1 world in 2 branches of your DisplayObject tree (separated cleanly), copying pixels for a split screen is a bad idea
data object to describe the world (not Sprite or DisplayObject)
Works very well so far. I've got 1 level, 2 players who move independently from each other and 2 screens that follow one player at a time. I see the other player in one player's screen and the one player in the other player's screen.
Here is how I did the data object part:
Define a central data object which describes the world and all it's world objects.
Write: make some sprites being able to manipulate 1 object of the world.
Read: update sprites by checking the properties of the world objects. 2 Screens -> 2 sprites for every world object. Check them every frame or try events.

Generating a tone using pure javascript with Chromium WebAudio API

How can I generate a tone (pure sine wave, for instance) using only javascript and Chromium's WebAudio API?
I would like to accomplish something like the Firefox equivalent.
The Chromium WebAudio demos here appear to all use prerecorded <audio> elements.
Thanks!
The Web Audio API has what's known as the Oscillator Interface to generate the tones you're talking about. They're pretty straight forward to get going...
var context = new webkitAudioContext(),
//Call function on context
oscillator = context.createOscillator(); // Oscillator defaults to sine wave
oscillator.connect(context.destination);
oscillator.start();
You can change the type of wave by doing:
oscillator.type = 1; // Change to square wave.
or alternatively:
oscillator.type = oscillator.SQUARE;
I've written an article about this very topic in more detail, so that might be of some use to you!
Probably not these best way, but I used dsp.js to generate different types of sinusoids, then passed them off to the Web Audio API in this demo: http://www.htmlfivewow.com/demos/waveform-generator/index.html