forked from: forked from: Mixing sounds bug *
forked from forked from: Mixing sounds bug * (diff: 1)
ActionScript3 source code
/**
* Copyright djankey ( http://wonderfl.net/user/djankey )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vbbe
*/
// forked from djankey's forked from: Mixing sounds bug *
// forked from djankey's Mixing sounds bug *
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;
import flash.net.FileReference;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.utils.ByteArray;
import flash.utils.getTimer;
import com.bit101.components.PushButton;
import com.bit101.components.Label;
public class FlashTest extends Sprite {
private var len:int = 6;
private var loaded:int = 0;
private var buttons:Array = new Array();
private var sounds:Array = new Array();
private var channels:Array = new Array();
private var buffers:Array = new Array();
private var playing:Array = new Array();
private static const BUFFER_SIZE:uint = 8192;
private static const FREQUENCY:uint = 44100;
private var ratio:Number = FREQUENCY / (BUFFER_SIZE * 1000);
private var output:Sound;
private var outputChannel:SoundChannel;
private var outputPosition:Number = 0;
private var outputTrack:ByteArray;
private var lbl:Label;
private var lbl2:Label;
private var labels:Array = new Array();
private var rec:PushButton;
private var mousePressed:Boolean = false;
private var recording:Boolean = false;
private var file:FileReference = new FileReference();
private var path:String = "http://www.as-flash.com/temp/sounds/";
public function FlashTest() {
// write as3 code here..
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
//________________________________________________________ Create buttons and load sounds
private function init(e:Event = null):void
{
// label 1
lbl = new Label(this, 0,0, "loading sounds:" + loaded + " / " + len);
// label 2
lbl2 = new Label(this, 0, 20, "");
// load
for(var i:int=0;i<len;i++) {
sounds[i] = new Sound();
sounds[i].load(new URLRequest(path + (i+1) + ".mp3"));
sounds[i].addEventListener(Event.COMPLETE, soundLoaded);
}
}
// sound loaded
private function soundLoaded(event:Event):void
{
loaded++;
lbl.text = "loading sounds:" + loaded + " / " + len;
if (loaded == len) extractSounds();
}
//________________________________________________________ Extract sounds
private function extractSounds():void
{
lbl2.text = "Extracting sounds";
var length:uint;
var steps:int;
var soundLength:uint;
var startTime:Number = getTimer();
for (var i:int = 0; i < len; i++) {
buffers[i] = new ByteArray();
length = Math.floor ((sounds[i].length / 1000) * FREQUENCY);
sounds[i].extract(buffers[i], length);
buffers[i].position = 0;
}
var time:Number = getTimer() - startTime;
lbl2.text = "Sounds extracted in " + time + "ms";
go();
}
//________________________________________________________ All sounds loaded
private function go():void
{
lbl.text = "Press REC and start recording your mix";
// output
output = new Sound();
outputChannel = new SoundChannel();
outputTrack = new ByteArray();
// setup buttons...
for(var i:int=0;i<len;i++){
var btn:PushButton = new PushButton(this, 0, 100 + i*22, "sound " + (i+1));
btn.addEventListener(MouseEvent.MOUSE_DOWN, btnDown);
btn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
btn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
buttons[i] = btn;
channels[i] = null;
playing[i] = false;
labels[i] = new Label(this, 120, 100 + i*22, "/");
}
// record button
rec = new PushButton(this, 0, 130+len*22, "REC", record);
// samples info
var samplesInfo:Label = new Label(this, 112, 77, "sample");
// mouse down
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
//________________________________________________________ mouse pressed?
private function mouseDown(event:MouseEvent = null):void
{
mousePressed = true;
}
private function mouseUp(event:MouseEvent = null):void
{
mousePressed = false;
}
//________________________________________________________ buttons actions
private function btnDown(event:MouseEvent):void
{
var id:int = getButtonID(event.currentTarget);
buttons[id].alpha = 0.5;
playSound(id);
}
private function btnOut(event:MouseEvent):void
{
var id:int = getButtonID(event.currentTarget);
buttons[id].alpha = 1;
}
private function btnOver(event:MouseEvent):void
{
if (mousePressed == true) {
var id:int = getButtonID(event.currentTarget);
buttons[id].alpha = 0.8;
playSound(id);
}
}
private function getButtonID(btn:Object):int
{
var id:int = -1;
for(var i:int=0;i<len;i++){
if(btn == buttons[i]){
id = i;
break;
}
}
return id;
}
//________________________________________________________ Play sound
private function playSound(id:int):void
{
if(channels[id]!=null){
channels[id].removeEventListener(Event.SOUND_COMPLETE, soundComplete);
channels[id].stop();
}
channels[id] = sounds[id].play(0);
buffers[id].position = 0;
channels[id].addEventListener(Event.SOUND_COMPLETE, soundComplete);
playing[id] = true;
}
//________________________________________________________ Sound complete
private function soundComplete(event:Event):void
{
var id:int = -1;
for(var i:int=0;i<len;i++){
if(channels[i] == event.target){
id = i;
break;
}
}
if(id>-1){
if(channels[id]!=null){
channels[id].removeEventListener(Event.SOUND_COMPLETE, soundComplete);
buffers[id].position = 0;
channels[id].stop();
}
playing[id] = false;
}
}
//________________________________________________________ record button pressed
private function record(event:MouseEvent):void
{
if(recording) {
lbl.text = "Press REC and start recording your mix";
rec.label = "REC";
recording = false;
outputPosition = outputChannel.position;
outputChannel.stop();
output.removeEventListener(SampleDataEvent.SAMPLE_DATA , onSoundData);
saveMixedTrack();
} else{
lbl.text = "Recording...";
rec.label = "SAVE MIX";
recording = true;
output.addEventListener(SampleDataEvent.SAMPLE_DATA , onSoundData );
outputChannel = output.play(outputPosition);
outputChannel.soundTransform = new SoundTransform(0);
}
}
//________________________________________________________ Sound data
private function onSoundData(sampleDataEvent:SampleDataEvent) : void
{
for (var i:int = 0; i < len; i++) {
var sample:int = -1;
if (playing[i] == true) sample = Math.floor(channels[i].position * ratio);
else buffers[i].position = 0;
labels[i].text = String(sample);
}
// write
for (var j:int = 0; j < BUFFER_SIZE; j++) {
var val:Number = 0;
var val2:Number = 0;
for (var k:int = 0; k < len; k++) {
if (playing[k] == true) {
if (buffers[k].position < buffers[k].length) val += buffers[k].readFloat();
if (buffers[k].position < buffers[k].length) val2 += buffers[k].readFloat();
}
}
sampleDataEvent.data.writeFloat(val);
sampleDataEvent.data.writeFloat(val2);
outputTrack.writeFloat(val);
outputTrack.writeFloat(val2);
}
}
//________________________________________________________ Save sound
private function saveMixedTrack():void
{
var startTime:Number = getTimer();
var encodedBA:ByteArray = FxWaveEncoder.encoder(outputTrack);
file.save(encodedBA, "mix.wav");
lbl.text = "Record your mix";
var encodingTime:Number = getTimer() - startTime;
lbl2.text = "Sound encoded in " + encodingTime + " ms";
}
}
}
// Wav encoder
// http://www.ceteris-paribus.info/article-29893316.html
import flash.utils.Endian;
import flash.utils.ByteArray;
import flash.events.Event;
class FxWaveEncoder
{
// writeHeader ( 2, 16, 44100 )
static public function encoder( pSamples:ByteArray, channels:int = 2, bits:int = 16, rate:int = 44100 ):ByteArray
{
var samples:ByteArray = new ByteArray();
samples.writeBytes( FxWaveEncoder.convert( pSamples ) );
var bytes: ByteArray = new ByteArray();
bytes.endian = Endian.LITTLE_ENDIAN;
bytes.writeUTFBytes( 'RIFF' );
bytes.writeInt( samples.length - 8 );
bytes.writeUTFBytes( 'WAVE' );
bytes.writeUTFBytes( 'fmt ' );
bytes.writeInt( int( 16 ) );
bytes.writeShort( int( 1 ) );
bytes.writeShort( channels );
bytes.writeInt( rate );
bytes.writeInt( int( rate * channels * ( bits / 8 ) ) );
bytes.writeShort( int( channels * ( bits / 8 ) ) );
bytes.writeShort( bits );
bytes.writeUTFBytes( 'data' );
bytes.writeInt( samples.length - 44 );
bytes.writeBytes( samples );
bytes.position = 0;
return bytes;
}
static private function convert( pBytes:ByteArray ):ByteArray
{
var ba:ByteArray = new ByteArray ( ) ;
ba.endian = Endian.LITTLE_ENDIAN;
pBytes.position = 0;
while( pBytes.position < pBytes.length ) ba.writeShort( pBytes.readFloat() * 32767 );
return ba;
}
}
