Record Sound Using AS3 Worker - actionscript-3

Hello I am trying to record the user sound using AS3 Worker everything works well when it comes to communication between the worker and the main scene but I think the record functionnality have and issue here I am using the Record Clash from bytearray.org (http://www.bytearray.org/?p=1858)
and here's is my code am I missing something :
package objects
{
import flash.events.Event;
import flash.system.MessageChannel;
import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.utils.ByteArray;
import starling.display.Button;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
public class RecordComponent extends Sprite
{
private var audioContainer:Image;
private var recButton:Button;
private var playButton:Button;
private var stopButton:Button;
//background thread for recording
private var worker:Worker;
private var wtm:MessageChannel;
private var mtw:MessageChannel;
private var output:ByteArray;
public function RecordComponent()
{
super();
worker = WorkerDomain.current.createWorker(Workers.RecordWorker);
wtm = worker.createMessageChannel(Worker.current);
mtw = Worker.current.createMessageChannel(worker);
worker.setSharedProperty("wtm",wtm);
worker.setSharedProperty("mtw",mtw);
worker.start();
wtm.addEventListener(flash.events.Event.CHANNEL_MESSAGE,onChannelMessage);
this.addEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
}
protected function onChannelMessage(event:flash.events.Event):void
{
output = wtm.receive();
}
protected function onAddedToStage(event:starling.events.Event):void
{
this.removeEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
drawScreen();
}
private function drawScreen():void
{
audioContainer = new Image( Assets.getAtlas().getTexture("audioContainer") );
addChild(audioContainer);
//record button
recButton = new Button( Assets.getAtlas().getTexture("recordButton") );
recButton.x=Math.ceil(194/2 - recButton.width/2);
recButton.y=5;
addChild(recButton);
//stop button
stopButton = new Button( Assets.getAtlas().getTexture("stopButton") );
stopButton.x=recButton.x+10;
stopButton.y=10;
stopButton.visible = false;
addChild(stopButton);
//play button
playButton = new Button( Assets.getAtlas().getTexture("playButton") );
playButton.x=Math.ceil(194 - playButton.width)-25;
playButton.y=10;
playButton.visible = false;
addChild(playButton);
this.addEventListener(starling.events.Event.TRIGGERED, buttons_triggeredHandler);
}
private function buttons_triggeredHandler(event:starling.events.Event):void
{
var currentButton:Button = event.target as Button;
switch(currentButton)
{
case recButton:
startRecording();
break;
case stopButton:
stopRecording();
break;
case playButton:
playRecording();
break;
}
}
private function playRecording():void
{
mtw.send("RECORD_PLAY");
}
private function stopRecording():void
{
stopButton.visible = false;
recButton.x = 25;
playButton.visible = true;
recButton.visible = true;
mtw.send("RECORD_STOP");
//
}
private function startRecording():void
{
recButton.visible = false;
stopButton.visible = true;
playButton.visible = false;
mtw.send("RECORD_START");
}
}
}
RecordWorker
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.media.Microphone;
import flash.system.MessageChannel;
import flash.system.Worker;
import org.as3wavsound.WavSound;
import org.bytearray.micrecorder.MicRecorder;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import org.bytearray.micrecorder.events.RecordingEvent;
public class RecordWorker extends Sprite
{
private var wtm:MessageChannel;
private var mtw:MessageChannel;
// volume in the final WAV file will be downsampled to 50%
private var volume:Number = .75;
// we create the WAV encoder to be used by MicRecorder
private var wavEncoder:WaveEncoder = new WaveEncoder( volume );
// we create the MicRecorder object which does the job
private var recorder:MicRecorder = new MicRecorder( wavEncoder,Microphone.getEnhancedMicrophone() );
public function RecordWorker()
{
wtm = Worker.current.getSharedProperty("wtm");
mtw = Worker.current.getSharedProperty("mtw");
mtw.addEventListener(Event.CHANNEL_MESSAGE,command_Handler);
}
//message received from the main component
protected function command_Handler(event:Event):void
{
switch(mtw.receive())
{
case "RECORD_START":
trace("recording.....");
recorder.record();
recorder.addEventListener(RecordingEvent.RECORDING, onRecording);
recorder.addEventListener(flash.events.Event.COMPLETE, onRecordComplete);
break;
case "RECORD_STOP":
trace("record stopped....");
recorder.stop();
break;
case "RECORD_PLAY":
if(recorder.output.length>0)
{
var player:WavSound = new WavSound(recorder.output);
player.play();
}
break;
}
}
private function onRecording(event:RecordingEvent):void
{
trace ( event.time );
}
private function onRecordComplete(event:flash.events.Event):void
{
}
}
}
anny help will be appriciated
Thanks,
Khaled

Looking at this write-up on Adobe's AS3 reference, it seems that because each created worker is "a virtual instance of the Flash runtime", it has no direct connection to any of the core runtime's input or output channels. The Microphone class is one such cut-off interface, which is why it can't reach the system mic inside a worker.

Related

Object Loading Issue

I am developing an application that consists of several different objects working together. Everything seems to work great, however, when I play this on a web server I notice the graphics and assets that are being loaded in from an external source are taking some time to load I'm not really sure what is going on I was hoping someone might provide some insight. Example, sometimes the graphic assets will not load at all, but audio seems to be loading in ok. Here is an example of my image loading class:
GFXReg.as
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.text.TextField;
public class GFXReg extends Sprite {
private var mc: MovieClip = new MovieClip();
private var loader: Loader = new Loader();
private var setW: Number;
public var setH: Number;
public var theH: Number;
private var bool: Boolean = false;
public function GFXReg(setSize: Boolean, W: Number, H: Number) {
bool = setSize;
if (bool) {
setW = W;
setH = H;
}
}
private function loadData(e: Event) {
if(loader.contentLoaderInfo.bytesLoaded == loader.contentLoaderInfo.bytesTotal){
addChild(loader);
}else{
var text:TextField = new TextField();
text.text = "Loading..."
addChild(text);
}
if (bool) {
loader.width = setW;
loader.height = setH;
}
}
public function theData(file: String): void {
loader.load(new URLRequest(file));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadData);
}
public function getBytes(str:String):int{
var num:int = 0;
switch(str){
case "loaded":
num = loader.contentLoaderInfo.bytesLoaded;
break;
case "total":
num = loader.contentLoaderInfo.bytesTotal;
break;
}
return num;
}
public function removeData():void{
loader.unloadAndStop(false);
trace("unload?");
}
private function unloadData(e:Event):void{
}
}
}
Main.as Sections(This loads in all the appropriate sections when prompted):
public function Main() {
xmlLoader = new XMLReg("config.xml", processXML);
}
private function processXML(e: Event): void {
theXML = new XML(e.target.data);
dir = theXML.MASTER.#DIRECTORY;
//BACKGROUND
bgGFX.theData(dir + theXML.MAINBG.#IMG);
//INITIALIZE
add(bgGFX,intro);
//INTRO WAS INSTANTIATED IN THE BEGINNING OF THIS CLASS
intro.start();
/*start method adds objects to stage, to test as a solution*/
addChildAt(header, numChildren);
//...
Also in my Main.as class I have a private method transition which loads in the appropriate sections after the previous sections have been completed these assets usually take a few seconds to load in I've noticed when working on a web server.
private function transition(e: Event): void {
//If intro is on the stage instantiate a new QuestionAnswer Object
if (intro.stage) {
header.enableMenu(true);
qa = new QuestAnswer(feedBool,nameCounter,nameVar);
qa.addEventListener("unload", transition);
qa.addEventListener("addFeed", setFeedFalse);
qa.addEventListener("addFeedTrue", setFeedTrue);
qa.addEventListener("enableHelp",enableHelp);
qa.addEventListener("getName",getName);
addChildAt(qa, numChildren-1);
remove(intro);
} else if (qa.stage) {
//If QuestionAnswer is on the Stage instantiate a new Results Object
header.enableMenu(true);
header.enableHelp(false);
results = new Results(qa.resultBundle());
results.addEventListener("unload", transition);
results.addEventListener("addFeed", setFeedFalse);
results.addEventListener("addFeedTrue", setFeedTrue);
results.addEventListener("setName",setName);
addChildAt(results, numChildren-1);
remove(qa);
} else if (results.stage) {
//If Results is on the stage loop back and instantiate a new QuestionAnswer Object
header.enableMenu(true);
header.enableHelp(false);
intro.enableAsset(true);
qa = new QuestAnswer(feedBool,nameCounter,nameVar);
qa.addEventListener("unload", transition);
qa.addEventListener("addFeed", setFeedFalse);
qa.addEventListener("addFeedTrue", setFeedTrue);
addChildAt(qa, numChildren-1);
trackAsset = true;
remove(results);
}
}

AS3: 1180 Call to a possibly undefined property: Add Child

Pretty big noob at AS3. I'm trying to Load a SWF into another file. (Main .fla loading external SWFS on mouse click)
I keep getting the error: 1180 Call to a possibly undefined property: Add Child, however.
My LoadSWF code is:
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class LoadSWF {
private var loaderFile: Loader;
private var swfFile: Object;
private var sourceFile: String;
private var fileLabel: String;
private var canDrag: Boolean;
private var popX: int;
private var popY: int;
public function LoadSWF(myFile: String, myLabel: String, myX: int = 0, myY: int = 0, myDrag: Boolean = false) {
// constructor code
trace("Loading SWF file:", myFile);
sourceFile = myFile;
fileLabel = myLabel;
canDrag = myDrag;
popX = myX;
popY = myY;
openSWF();
}
private function openSWF(): void {
// initialise variables
loaderFile = new Loader();
swfFile = addChild(loaderFile);
// set initial position of the SWF popup
loaderFile.x = popX;
loaderFile.y = popY;
try {
loaderFile.load(new URLRequest(sourceFile));
// runs after the SWF popup has finished loading
loaderFile.contentLoaderInfo.addEventListener(Event.COMPLETE, SWFloaded);
} catch (err: Error) {
// provide some error messages to help with debugging
trace("Error loading requested document:", sourceFile);
trace("Error:", err);
sourceFile = null;
}
} //end openSWF
private function SWFloaded(evt: Event): void {
// and add the required event listeners
loaderFile.addEventListener(MouseEvent.MOUSE_DOWN, dragSWF);
loaderFile.addEventListener(MouseEvent.MOUSE_UP, dropSWF);
// use the POPUP reference to access MovieClip content
swfFile.content.gotoAndStop(fileLabel);
// assigns a close function to the button inside the popup
swfFile.content.closeBtn.addEventListener(MouseEvent.CLICK, closeSWF);
// remove the COMPLETE event listener as it’s no longer needed
loaderFile.contentLoaderInfo.removeEventListener(Event.COMPLETE, SWFloaded);
} //end SWFLOaded
private function dragSWF(evt: MouseEvent): void {
swfFile.content.startDrag();
}
private function dropSWF(evt: MouseEvent): void {
swfFile.content.stopDrag();
}
private function closeSWF(evt: MouseEvent): void {
// remove the required event listeners first
loaderFile.removeEventListener(MouseEvent.MOUSE_DOWN, dragSWF);
loaderFile.removeEventListener(MouseEvent.MOUSE_UP, dropSWF);
swfFile.content.closeBtn.removeEventListener(MouseEvent.CLICK, closeSWF);
// remove the pop-up
loaderFile.unloadAndStop();
}
} //end class
} //end package
I'm calling it into my main class file, which code is (I left out the rest, guessing its unnecessary):
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.utils.Dictionary;
import flash.text.TextFormat;
import flash.net.*;
import flash.events.*;
import fl.controls.*;
import flash.media.*;
import fl.events.ComponentEvent;
import fl.managers.StyleManager;
import fl.data.DataProvider;
import fl.data.SimpleCollectionItem;
import fl.managers.StyleManager;
import fl.events.ComponentEvent;
import flash.events.Event;
import flash.net.SharedObject;
import LoadSWF;
public class Main extends MovieClip {
//Declare variables
private var componentFmt: TextFormat;
private var radioBtnFmt: TextFormat;
private var playerData: Object;
private var savedGameData: SharedObject;
// Pop-up Variables
private var popupFile: LoadSWF;
private var swfPath: String;
public function Main() {
// constructor code
this.savedGameData = SharedObject.getLocal("savedPlayerData");
this.setComponents();
this.setPlayerData();
//this.swfPath = "";
//this.isHelpOpen = false;
//this.sndPath = "musicSFX/music2.mp3";
//this.isMuted = false;
//this.sndTrack = new LoadSND(this.sndPath, this.canRepeat);;
//this.muteBtn.addEventListener(MouseEvent.CLICK, this.setMute);
swfPath = "";
helpBtn.addEventListener(MouseEvent.CLICK, openSWF);
//hauntedForestBtn.addEventListener(MouseEvent.CLICK, openSWF);
}
public function openSWF(evt: MouseEvent): void {
// determine which button was pressed
var myFile: String = evt.currentTarget.name.replace("Btn", ".swf");
myFile = (swfPath == "") ? myFile : swfPath + myFile;
if (myFile == "help.swf") {
// load the help SWF file - is draggable
swfFile = new LoadSWF(myFile, currentFrameLabel, 80, 60, true);
} else {
// load the selected SWF file - is not draggable
swfFile = new LoadSWF(myFile, currentFrameLabel);
}
addChild(swfFile);
}
If anyone could help me find a solution, i'd greatly appreciate it.
Thanks :)
addChild is defined by DisplayObjectContainer.
So to access this function, you'll have to alter LoadSWF so that it extends DisplayObjectContainer.

AS3 Error 1195:

I am getting the following errors:
C:\Users\Admin\Desktop\Final Project\Main.as, Line 80, Column 14 1195:
Attempted access of inaccessible method setTrackData through a
reference with static type LoadSND.
Relevant code
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.utils.Dictionary;
import flash.text.TextFormat;
import flash.net.*;
import flash.events.*;
import fl.controls.*;
import flash.media.*;
import fl.events.ComponentEvent;
import fl.managers.StyleManager;
import fl.data.DataProvider;
import fl.data.SimpleCollectionItem;
import fl.managers.StyleManager;
import fl.events.ComponentEvent;
import flash.events.Event;
import flash.net.SharedObject;
import LoadSWF;
import GameButton;
import LoadSND;
public class Main extends MovieClip {
//Declare variables
private var componentFmt: TextFormat;
private var radioBtnFmt: TextFormat;
private var playerData: Object;
private var savedGameData: SharedObject;
// Pop-up Variables
private var popupFile: LoadSWF;
private var swfPath: String;
private var swfFile: LoadSWF;
//Sound Variables
private var MAX_TRAX: int = 7;
private var MAX_SFX: int = 9;
private var sndPath: String;
private var sndTrack: LoadSND;
private var isMuted: Boolean;
private var canRepeat: Boolean;
private var sndVolume: Number;
private var sndChannel: SoundChannel;
public function Main() {
// constructor code
this.savedGameData = SharedObject.getLocal("savedPlayerData");
this.setComponents();
this.setPlayerData();
swfPath = "";
sndPath = "musicSFX/Fury.mp3"; //default track
isMuted = false;
sndTrack = new LoadSND(sndPath, canRepeat);
}
/********************************************************
Load SND Functions***************************************
********************************************************/
private function setSound(evt: Event): void {
// Process COMBO BOX changes
if (musicCombo.selectedItem.data == "none") {
// no music is required so stop sound playing
SoundMixer.stopAll();
} else {
// otherwise load in the selected music
sndPath = "musicSFX/" + musicCombo.selectedItem.data;
sndTrack.setTrackData(sndPath, canRepeat);
}
}
private function setSlider(evt: Event): void {
// identify the button clicked
var mySlider: Object = (evt.target);
// adjusting to volume of the music channel to slider value
sndTrack.setVolumeLevel(mySlider.value);
}
private function setVolumeLevel(myVolume: Number): void {
// change the volume when slider changed
sndVolume = myVolume;
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
}
Also: the LoadSND Class
package {
import flash.events.*;
import flash.media.*;
import flash.net.URLRequest;
import flash.display.MovieClip;
public class LoadSND extends MovieClip {
//declare variables
private var sndTrack: Sound;
private var sndChannel: SoundChannel;
private var sndVolume: Number;
private var newTrack: String;
private var canRepeat: Boolean;
public function LoadSND(myTrack: String, myRepeat: Boolean = true) {
// constructor code
// set a default volume and track
sndVolume = 0.5;
setTrackData(myTrack, myRepeat);
}
private function loadSound(): void {
// first stop all old sounds playing
SoundMixer.stopAll();
// create a new sound for the track and a new sound channel
sndTrack = new Sound();
sndChannel = new SoundChannel();
// load the required sound
sndTrack.load(new URLRequest(newTrack));
// when loaded – play it;
sndTrack.addEventListener(Event.COMPLETE, soundLoaded);
}
private function soundLoaded(evt: Event): void {
// finished with this listener so remove it
//sndTrack.removeEventListener(Event.COMPLETE, soundLoaded);
// call the play sound function
playSound();
}
private function playSound(): void {
// assign music to the musicChannel and play it
sndChannel = sndTrack.play();
// setting the volume control property to the sound channel
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
// but add this one to make repeats
sndChannel.addEventListener(Event.SOUND_COMPLETE, playAgain);
}
private function playAgain(evt: Event): void {
// remove this listener and repeat playSound()
sndChannel.removeEventListener(Event.SOUND_COMPLETE, playAgain);
playSound();
}
private function setTrackData(myTrack: String, myRepeat: Boolean): void {
// update the new track information
newTrack = myTrack;
canRepeat = myRepeat;
// and load it
loadSound();
}
private function setVolumeLevel(myVolume: Number): void {
// change the volume when slider changed
sndVolume = myVolume;
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
}
} //end class
} //end package
Appreciate all the help :) thanks
Your setTrackData function in LoadSND class is private. you need to change type of the function to public so that you have access this function from the main class.
so change you function like this
public function setTrackData(myTrack: String, myRepeat: Boolean): void {
// update the new track information
newTrack = myTrack;
canRepeat = myRepeat;
// and load it
loadSound();
}

Actionscript 3: Event.SOUND_COMPLETE doesn't fire

Okay, so i was working on my simple actionscript-3 sound player for a website I'm making...
and while doing so it occured to me that the SOUND_COMPLETE event doesn't fire for some reason. So if anyone seems to notice the problem in my code, please respond!
package {
import flash.events.*;
import flash.media.*;
import flash.external.*;
import flash.net.*;
import flash.utils.*;
public class player{
private var soundChannel:SoundChannel;
private var sound:Sound;
private var lastPosition:Number = 0;
public function player():void{
ExternalInterface.addCallback("load", this.load);
ExternalInterface.addCallback("play", this.play);
ExternalInterface.addCallback("stop", this.stop);
ExternalInterface.addCallback("reset", this.reset);
}
/*
javascript from inside actionscript:
ExternalInterface.call("console.log","ipsum");
*/
private function load(url:String):void{
var audio:URLRequest = new URLRequest(url);
try {
this.soundChannel.stop();
} catch(e:Error) {
};
this.sound = new Sound();
this.sound.load(audio);
this.lastPosition = 0;
}
private function play():void{
this.soundChannel = this.sound.play(this.lastPosition);
this.soundChannel.addEventListener(Event.SOUND_COMPLETE,finished);
ExternalInterface.call("console.log","started playing");
}
private function finished():void{
this.lastPosition=0;
this.soundChannel=this.sound.play()
ExternalInterface.call("console.log","finished playing");
}
private function reset():void{
this.lastPosition = 0;
this.soundChannel.stop();
}
private function stop():void{
try {
this.lastPosition = this.soundChannel.position;
this.soundChannel.stop();
} catch(e:Error) {
};
}
}
}//package
I believe the problem is that finished() doesn't accept an event, it should be :
private function finished(e:Event):void{
this.lastPosition=0;
this.soundChannel=this.sound.play()
ExternalInterface.call("console.log","finished playing");
}

flex 4: window system development ideas

My application will need some windows but I can't use the popUpManager to handle custom components so I'm thinking to implement a new window system.
But I still don't know how to merge it with my custom components. Any ideas?
My code:
My login skin:
<s:Skin(...)>
<s:Group>
(...login components...)
</s:Group>
</s:Skin>
package com.totty.app.components.login {
import com.totty.app.TottysBrain;
import com.totty.app.components.window.Window;
import com.totty.app.events.LoginSuccessEvent;
import com.totty.tottysBrain.components.BrainyDynComponent;
import com.totty.tottysBrain.components.BrainyWindow;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
import spark.components.Button;
import spark.components.CheckBox;
import spark.components.Group;
import spark.components.Label;
import spark.components.TextInput;
import spark.components.supportClasses.SkinnableComponent;
[Event(name="loginSuccess", type="com.totty.app.events.LoginSuccessEvent")]
public class Login extends BrainyDynComponent {
[SkinPart(required="true")]
public var email:TextInput;
[SkinPart(required="true")]
public var password:TextInput = new TextInput();
[SkinPart(required="false")]
public var rememberMe:CheckBox;
[SkinPart(required="false")]
public var notification:Label;
[SkinPart(required="true")]
public var submit:Button = new Button();
private var _currentState:uint = 0;
private var _states:Array = ['default', 'logging', 'loginFailure', 'loginSuccess'];
private var _default:Boolean = false;
private var _logging:Boolean = false;
private var _loggingSuccess:Boolean = false;
private var _loggingFailure:Boolean = false;
public function Login() {
super();
defaultCommand = 'users.login';
defaultSkin = LoginSkin;
_setCurrentState(0);
onPartAdded('submit', function():void {
submit.addEventListener(MouseEvent.CLICK, _submitLoginButton_click);
});
onPartRemoved('submit', function():void {
submit.removeEventListener(MouseEvent.CLICK, _submitLoginButton_click);
});
onPartAdded('window', function():void{
//window.addEventListener('close', _window_close);
//window.title = 'Login';
});
}
private function _window_close(evt:Event):void{
dispatchEvent(evt);
var parentAsGroup:Group = parent as Group
parentAsGroup.removeElement(this);
}
protected function _submitLogin():void {
_setCurrentState(1);
submitData({email:email.text, password:password.text, rememberMe:rememberMe.selected});
}
override protected function _onSuccess(result:*):void {
Alert.show(result);
_setCurrentState(3);
if(result) {
dispatchEvent(new LoginSuccessEvent(email.text, rememberMe.selected));
_loggingSuccess = true;
}else{
_setCurrentState(4);
_loggingSuccess = false;
}
}
override protected function _onFailure(result:*):void {
Alert.show(result);
_setCurrentState(4);
_loggingSuccess = false;
}
private function _submitLoginButton_click(evt:MouseEvent):void {
_submitLogin();
}
private function _setCurrentState(n:uint):void{
if(_currentState == n) return;
_currentState = n;
invalidateProperties();
}
override protected function commitProperties():void{
super.commitProperties();
switch(_currentState){
case 0:
// default
//window.footerText = '';
break;
case 1:
// logging
//window.footerText = 'logging';
break;
case 2:
// loginFailure
//window.footerText = 'loginFailure';
break;
case 3:
// loginSuccess
//window.footerText = 'loginSuccess';
//parentBrain.removeElement(this);
//var parentAsGroup:Group = parent as Group
//PopUpManager.removePopUp(this);
//parentAsGroup.removeElement(this);
break;
}
}
}
}`
Now I have the main application to add this component in a window. I would prefer to be able to be able to see the window while I'm designing the interface. That means that the window component must be added to the component. Not to use the but something like to contain all the contents of the component.
Maybe you already saw this, but its a good place to start, anyway :)
http://code.google.com/p/flexmdi/