Actionscript 3: Monitoring the activity level for multiple Microphones doesn't seem to work - actionscript-3

For a project I want to show all available webcams and microphones, so that the user can easily select whichever webcam/microphone combination they prefer. I run into an issue with the microphones listing though.
Each microphone is listed with an activity animation and it's name. I am able to list all Microphones just fine (using the Microphone.names Array), but it seems like I can only get the activity viewer to work for one microphone. The other microphones show up with '-1' activity, which (as far as I know) is Flex for 'present, but not in use'. When unplugging the microphone that does show activity, the next one (in my case, the mic-in line on my motherboard) shows up with '0' activity (it's not connected, so that makes sense).
During my testing I have a total of 3 microphones available, the not-connected onboard mic-in port, and two connected microphones.
For testing purposes I use a timer that traces the current microphone activity each 100ms and the graph is also shown.
It does not seem to matter what default microphone I set via flash' settings panel.
The code
I've only attached the revelant code snippets below to make it easier for you to read through them. Please let me know if you prefer the entire code.
Main application.mxml
Note: cont is a VBox. i is defined before this code snippet.
var mics:Array = Microphone.names;
for(i=0; i < mics.length; i++){
var mic:settingsMicEntry = new assets.settingsMicEntry;
mic.d = {name: mics[i], index: i};
cont.addChild(mic);
}
assets/settingsMicEntry.mxml
timer is defined before this code snippet. the SoundTransform is added to silence local microphone playback. Excluding this code does not solve the problem, sadly (I've tried). display is an MXML Canvas object.
mic = Microphone.getMicrophone(d.index);
if(mic){
// Temporary: The Microphones' visualizer
var bar:Box = new Box();
bar.y = 50;
bar.height = 0;
bar.width = 66;
bar.setStyle("backgroundColor", 0x003300);
display.addChild(bar);
var tf:SoundTransform = new SoundTransform(0);
mic.setLoopBack(true);
mic.soundTransform = tf;
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void{
var h:int = Math.floor((display.height/100)*mic.activityLevel);
bar.height = (h>-1) ? h : 0;
bar.y = (h>-1) ? display.height-h : display.height;
trace('TIMER: '+h+' from '+d.name);
});
timer.start();
}
I'm pulling my hear out here, so any help is much appreciated!
Thanks,
-Dave
Ps.: Pardon the messiness of the code!

You can set up a mock NetStream connection using the OSMF library.
You'll need to import the classes from the NetMocker project (under libs/adobe - org.osmf.netmocker) and the classes NetConnectionCodes and NetStreamCodes (under framework/OSMF - org.osmf.net).

Check out that you need to create one NetStream for each microphone

Related

How to get duration of speech synthesizer stream

How can I measure duration of SpeechSynthesierStream before playing it please?
SpeechSynthesizer ss = new SpeechSynthesizer();
SpeechSynthesisStream sss;
ss.Voice = SpeechSynthesizer.AllVoices[3];
sss = await ss.SynthesizeTextToStreamAsync("Hello world.");
MediaElement mediaElement = new MediaElement();
mediaElement.SetSource(sss, sss.ContentType);
//here I want to get the duration
mediaElement.Play();
This code works just fine and speaks "Hello world.". After some time the mediaElement.NaturalDuration has also correct value. But I need to know duration of speech as soon as possible and before playing the speech. I added handler for mediaElement.MediaOpen, but this "SetSource" probably doesn't fire this event. Thank you.
In order for MediaOpen to fire, you need to attach the MediaElement to the visual tree. Once you've attached the MediaElement to the visual tree, NaturalDuration should be available within the MediaOpen event.

Getting Bitmap from Video decoded with Nestream AppendBytes (AS3)?

I am wondering if someone who has handled NetStream.appendBytes in Flash knows how to get the bitmapData from a decoded video frame? I have already looked at this question but that is from 3 years ago and the more recent comment/answer seems to be gone. In 2014 has anyone managed to turn those bytes into a bitmap? I am working with Flash Player 11.8 and this is not a desktop/AIR app.
In the image below I can do steps 1) and 2) but there's a brick wall at step 3)
The problem is that simply using bitmapdata.draw(video_container); does not work but instead it throws a Policy File error even though I am using a byteArray (from local video file in the same directory as the SWF). No internet is even involved but Flash tells me that "No Policy File granted permission from the server" or such nonsense. I think the error is just a bail-out insteading of straight up saying "You are not allowed to do this.."
I have tried: trying to appease this Crossdomain.xml issue anyway and looking into all known security/domain settings. I came to the conclusion that the error is not the problem but a side effect of the issue.. The issue here being that: Flash Player is aware of the SWF's location and of any files local to it. That's okay when you pass a String as URL etc but when the Netstream data is not local to the SWF domain then it becomes a Policy File issue. Problem is my data is in the Memory not in a folder like the SWF and therefore cannot alllow bitmapData.draw since it cannot "police" an array of bytes, any known fixes for this?... (I can't even say the words I really wanted to use).
What I am trying to achieve: Is to essentially use Netstream as an H.263 or H.264 image decoder in the same way Loader is a JPEG-to-Bitmap decoder or LoadCompressed.. is an MP3-to-PCM decoder. You know, access the raw material (here RGB pixels), apply some effects functions and then send to screen or save to disk.
I know it is a little late, but I think I found a solution for your problem.
So, to avoid the Security sandbox violation #2123 Error, you have just to do like this :
// ...
net_stream.play(null);
net_stream.play('');
// ...
Hope that can help.
I know this question is a couple months old, but I wanted to post the correct answer (because I just had this problem as well and other will too).
Correct answer:
It's a bug that has been open at adobe for almost 2 years
Link to the bug on Adobe
Work Around until the bug gets fixed (I am using this and it works great):
Workaround using Sprite and graphics
To take a snapshot from a video stream we don't need NetStream.appendBytes which inject data into a NetStream object.
For that we can use BitmapData.draw which has some security constraints. That's why in many times we get a flash security error. About that, Adobe said :
"... This method is supported over RTMP in Flash Player 9.0.115.0 and later and in Adobe AIR. You can control access to streams on Flash Media Server in a server-side script. For more information, see the Client.audioSampleAccess and Client.videoSampleAccess properties in Server-Side ActionScript Language Reference for Adobe Flash Media Server. If the source object and (in the case of a Sprite or MovieClip object) all of its child objects do not come from the same domain as the caller, or are not in a content that is accessible to the caller by having called the Security.allowDomain() method, a call to the draw() throws a SecurityError exception. This restriction does not apply to AIR content in the application security sandbox. ...".
For crossdomain file creation and some other security config for AMS server, you can take a look on this post : Crossdomain Video Snapshot - Fixing BitmapData.draw() Security Sandbox Violation.
After allowing our script to get data from our video stream, we can pass to the code.
I wrote a code that play a video stream ( rtmp or http ) and take a snapshot to show it in the stage or save it as a file after applying a pixel effect :
const server:String = null; //'rtmp://localhost/vod'
const stream:String = 'stream'; // 'mp4:big_buck_bunny_480p_h264.mp4';
var nc:NetConnection;
var ns:NetStream;
var video:Video;
const jpg_quality:int = 80;
const px_size:int = 10;
nc = new NetConnection();
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent):void{});
nc.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{
if(e.info.code == 'NetConnection.Connect.Success'){
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{});
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent):void{});
video = new Video(320, 180);
video.x = video.y = 10;
video.attachNetStream(ns);
addChild(video);
ns.play(stream);
}
})
nc.connect(server);
btn_show.addEventListener(
MouseEvent.CLICK,
function(e:MouseEvent): void{
var bmp:Bitmap = pixelate(video, px_size);
bmp.x = 10;
bmp.y = 220;
addChild(bmp);
}
)
btn_save.addEventListener(
MouseEvent.CLICK,
function(e:MouseEvent): void{
var bmp:Bitmap = pixelate(video, px_size);
var jpg_encoder:JPGEncoder = new JPGEncoder(80);
var jpg_stream:ByteArray = jpg_encoder.encode(bmp.bitmapData);
var file:FileReference = new FileReference();
file.save(jpg_stream, 'snapshot_'+int(ns.time)+'.jpg');
}
)
function pixelate(target:DisplayObject, px_size:uint):Bitmap {
var i:uint, j:uint = 0;
var s:uint = px_size;
var d:DisplayObject = target;
var w:uint = d.width;
var h:uint = d.height;
var bmd_src:BitmapData = new BitmapData(w, h);
bmd_src.draw(d);
var bmd_final:BitmapData = new BitmapData(w, h);
var rec:Rectangle = new Rectangle();
rec.width = rec.height = s;
for (i = 0; i < w; i += s){
for (j = 0; j < h; j += s){
rec.x = i;
rec.y = j;
bmd_final.fillRect(rec, bmd_src.getPixel32(i, j));
}
}
bmd_src.dispose();
bmd_src = null;
return new Bitmap(bmd_final);
}
Of course, this is just a simple example to show the manner to get a snapshot from a video stream, you should adapt and improve it to your needs ...
I hope all that can help you.

nonClickable buttons after loading same FLA 2nd time

Basically Im trying to make a FLA where if i click a button and close the FLA, next time I load the same FLA, the buttons that have been clicked before , now have an alpha of 0.5 and are nonClickable.
Currently i have only the logic for creating the buttons and saving the data:
private var savedData:SharedObject = SharedObject.getLocal("sharedStorage10");
private var buttonInfoArr:Array = [];
public function Main()
{
for (var i:int = 0; i < 4; i++)
{
var myImage_mc:MovieClip = new MovieClip();
myImage_mc.graphics.beginFill( 0xFFFFFF * Math.random() );
myImage_mc.graphics.drawRect(0,0,100,100);
myImage_mc.graphics.endFill();
myImage_mc.x = 50 + i * (myImage_mc.width + 10);
myImage_mc.y = 100;
myImage_mc.name = "myImage_mc" + i
this.addChild(myImage_mc);
myImage_mc.mouseEnabled = true;
myImage_mc.buttonMode = true;
myImage_mc.addEventListener(MouseEvent.CLICK, onClick);
}
}
private function onClick(ev:MouseEvent):void
{
var thisButton:MovieClip = ev.currentTarget as MovieClip
trace(thisButton.name)
thisButton.alpha = 0.5
thisButton.buttonMode = false;
thisButton.removeEventListener(MouseEvent.CLICK, onClick);
buttonInfoArr.push( thisButton.name );
savedData.data.myArray = buttonInfoArr;
}
But i dont know how to load/use the data and make the buttons (that have been clicked before) start with an alpha of 0.5 and without an EventListener(MouseEvent.CLICK, onClick)
PS:Could it be done without the use of Dictionary, cause i haven`t grasp my mind over it yet.
_EDIT__
to represent my problem in a more detailed way:
So im creating a game in which I collect objects that represent money.After I die in the game i get into the Shop Class in which i can buy different items depending on the money i have.
So lets say that after dying i have enough money to get item1 and item2. So i Click on button1 (representing item1) and button2 (representing item2) (when clicked their alpha gets to 0.5) and start the game again.Ok so now i have 1 life more and i get more money.But suddenly out of nowhere i feel something strange deep in me, something that i have never felt before -> HUNGER,
I shut down the PC (cause I love Earth )and run as fast as possible to the nearest shop.
lets say item1 is : +1life and item2 is : get more money from objects
After I had satisfied my primal needs I feel the strong urge to play that awesome game of mine again. But when i start the game I start to see some strange things: It seems that I havent got one life more and neither do i get more money and just to be sure that Im not hallucinating (or that i didnt rememer the lifes i had last time) I die on purpose so the Shop menu shows. So now what I see is making me sad -> button1 and button2 are active and have an alpha of 1( and that means that the game thinks that they were never bought/clicked, that i have never played this game before in my life)
So i go crazy (cause all that play before was for nothing and i have to start all over again).
After i calm down, I decide to change my life. 1st BIG change is adding some code into the game. To be more specific: a method that will save the items that i bougth, so when i close the game and start again the things i see will bring joy to my life - >: I still have the items that i bougth last time.
So long story short:
how do i make that when i click a button (it changes its alpha to 0.5)and close the FLA ,
whenever i open the same FLA, the button that i clicked before will be shown as clicked now(it alpha will be 0.5)
What is happening is normal. All variables are stored in RAM, which is temporary memory. Your button states are variables, too. Whenever any program closes, everything it has in RAM is deleted, thus the variables are cleared. This is true of all programs, in all programming languages. There are absolutely no exceptions.
Quite simply, you need to create a file that can store all this data long-term, on the hard drive (which is "permanent" memory).
If you're creating a game for the internet, you're going to need to store this data using SharedObjects (a.k.a. cookies).
If you're creating a game to be installed on the computer or mobile, you'll want to store data in a file. I recommend XML files, as they're the easiest to work with by far.
I am not going into either here, because those are lectures, not SO answers. See the above links to get started.
I didn't understand what exactly you're trying to do. But here is my simply approach would be that way.
// this is basically saved your latest clip we will control this if user click this button then we will be blocked
private var lastClickedButton:MovieClip;
private function onClick(ev:MouseEvent):void
{
var thisButton:MovieClip = ev.currentTarget as MovieClip
trace(thisButton.name)
thisButton.alpha = 0.5
thisButton.buttonMode = false;
thisButton.removeEventListener(MouseEvent.CLICK, onClick);
buttonInfoArr.push( thisButton.name );
savedData.data.myArray = buttonInfoArr;
// set the lastclicked button
lastClickedButton = thisButton;
// save this savedData sharedObject
savedData.data.lastClickedItem = lastClickedButton;
}
addEventListener(Event.ENTER_FRAME, loop)
{
if(savedData.data.lastClickedItem)
{
// do something here.
lastClickedButton.alpha = 0.5;
lastClickedButton.mouseEnabled=false;
// clear your sharedobject
savedData.flush();
}
}
I hope this will help you. good luck...

Using a Numeric Stepper from one Flash file to affect gamespeed in an external Flash file? Actionscript 3.0

Currently I have an intro screen to my flash file which has two objects.
A button which will load an external flash file using:
var myLoader:Loader = new Loader();
var url:URLRequest = new URLRequest("flashgame.swf");
The second thing is a Numeric Stepper, which will be from 1 to 10. If the user selects a number e.g. 3 then the game speed I have set in the flashgame.swf should be changed
Such as:
var gameSpeed:uint = 10 * numericStepper.value;
But I think my problem is coming into place because the stepper and gamespeed are from different files.
Anyone got any idea please?
I have also tried creating a stepper in the game file and used this code:
var gameLevel:NumericStepper = new NumericStepper();
gameLevel.maximum = 10;
gameLevel.minimum = 1;
addChild(gameLevel);
var gameSpeed:uint = 10 * gameLevel.value;
For some reason the stepper just flashes on the stage, no errors come up and the game doesn't work
When you execute you code, the stepper has no chance to wait for user input.
There is no time between theese two instructions.
addChild(gameLevel);
var gameSpeed:uint = 10 * gameLevel.value;
You should wait for user input in your NumericStepper, and then, on user event, set the game speed.
Edit: Yeah I know it's kinda sad to type out all this code (especially since some people wouldn't even be grateful enough to say thanks) but I think this question is important enough to justify the code as it may be helpful to others in future also.
Hi,
You were close. In your game file you could have put a var _setgameSpeed and then from Intro you could adjust it by flashgame._setgameSpeed = gameSpeed; It's a bit more complicated though since you also have to setup a reference to flashgame in the first place. Let me explain...
Ideally you want to put all your code in one place (an .as file would be best but...) if you would rather use timeline then you should create a new empty layer called "actions" and put all your code in the first frame of that.
Also change your button to a movieClip type and remove any code within it since everything will be controlled by the code in "actions" layer. In the example I have that movieclip on the stage with instance name of "btn_load_SWF"
Intro.swf (Parent SWF file)
var my_Game_Swf:MovieClip; //reference name when accessing "flashgame.swf"
var _SWF_is_loaded:Boolean = false; //initial value
var set_gameSpeed:int; //temp value holder for speed
var swf_loader:Loader = new Loader();
btn_load_SWF.buttonMode = true; //instance name of movieclip used as "load" button
btn_load_SWF.addEventListener(MouseEvent.CLICK, load_Game_SWF);
function load_Game_SWF (event:MouseEvent) : void
{
//set_gameSpeed = 10 * numericStepper.value;
set_gameSpeed = 100; //manual set cos I dont have the above numericStepper
if ( _SWF_is_loaded == true)
{
stage.removeChild(swf_loader);
swf_loader.load ( new URLRequest ("flashgame.swf") );
}
else
{ swf_loader.load ( new URLRequest ("flashgame.swf") ); }
swf_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, Game_SWF_ready);
}
function Game_SWF_ready (evt:Event) : void
{
swf_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, Game_SWF_ready);
//Treat the Loader contents (flashgame.swf) as a MovieClip named "my_Game_Swf"
my_Game_Swf = swf_loader.content as MovieClip;
my_Game_Swf.gameSpeed = set_gameSpeed; //update gameSpeed variable in flashgame.swf
//also adjust SWF placement (.x and .y positions etc) here if necessary
stage.addChild(my_Game_Swf);
_SWF_is_loaded = true;
}
Now in you flashgame file make sure the there's also an actions layers and put in code like this below then compile it first before debugging the Intro/Parent file. When your Intro loads the flashgame.swf it should load an swf that already has the code below compiled.
flashgame.swf
var gameSpeed:int;
gameSpeed = 0; //initial value & will be changed by parent
addEventListener(Event.ADDED_TO_STAGE, onAdded_toStage);
function onAdded_toStage (e:Event):void
{
trace("trace gameSpeed is.." + String(gameSpeed)); //confirm speed in Debugger
//*** Example usage ***
var my_shape:Shape = new Shape();
my_shape.graphics.lineStyle(5, 0xFF0000, 5);
my_shape.graphics.moveTo(10, 50);
my_shape.graphics.lineTo(gameSpeed * 10, 50); //this line length is affected by gameSpeed as set in parent SWF
addChild(my_shape);
}
The key line in intro.swf is this: my_Game_Swf.gameSpeed = set_gameSpeed; as it updates a variable in flashgame.swf (referred as my_Game_Swf) with an amount that is taken from a variable in the Parent SWF.
This is just one way you can access information between two separate SWF files. Hope it helps out.

add equalizer for online flash radio

i have tried add equalizer my online radio. i was used http://www.everyday3d.com/blog/index.php/2008/03/26/classic-sound-equalizer-in-flashas3/
flash source file . it's working fine when i am worked in flash ide. but on my server the equalizer doesnot show. but if the playing file is mp3 format it will worked but if we play the stream url it's not working. i dont know how can i fix this. i am using as3, i am new to flash. please help any one. thanks advance
the equalizer code
var es:EqualizerSettings = new EqualizerSettings();
es.numOfBars = 80;
es.height = 30;
es.barSize = 3;
es.vgrid = true;
es.hgrid = 2;
es.colorManager = new GradientBarColor(0xffff4444);
es.effect = EqualizerSettings.FX_REFLECTION;
var e:Equalizer = new Equalizer();
e.update(es);
e.x = 100;
e.y = 60;
addChild(e);
addEventListener(Event.ENTER_FRAME, e.render);
What Gio said, SoundMixer.computeSpectrum-based approach, such as the one linked in your question, suffers from security problems. But there are alternatives, for example check this code: http://wonderfl.net/c/euIb/read (some of stream URLs in it are dead, and it might not work right away - so try it with your own stream URL)