Search code examples
flashactionscript-3microphone

Flash 10.1 AS3 - Applying realtime effects to Microphone - stutter problems


I'm trying to write a flash application which takes a Microphone stream and applies realtime effects and outputs this back to the speakers.

I'm finding I'm having problems with stuttering when taking the output from the mic, copying this into a ByteArray amd then using a seperate

sound = new Sound();

sound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound);

sound.play();

to read from this ByteArray and play back the sound.

I have noticed that the input from the mic's bytesAvailable changes, and also that the two events (the mic's SAMPLE_DATA and the sound's SAMPLE_DATA) aren't firing A B A B A B A B like would be needed but is more random.

Am I right in thinking that the mic.SAMPLE_DATA event fires at different intervals with different amounts of data and a working implementation would need to read the available data in and buffer the input so that the Sound SampleDataEvent would always have something to play back to avoid the stuffering?


Solution

  • I found a solution so thought I'd post it on here incase anyone else had similar problems (many google searches turned up nothing for me).

    It does seem that the input from the mic is fed through inconsistently, and all the bytes sent through are needed in order to properly process the sound. The key to getting it to work was to use an array to buffer the input.

    private var mic:Microphone;
    private var micBuffer:Array;
    private var playBackSound:Sound;
    //the effect I was applying needed to be applied to 
    private var _leftChannel:Vector.<Number> = new Vector.<Number>(8192/2);
    
    private function init() {
        micBuffer = new Array();
        mic = Microphone.getMicrophone();
        mic.rate = 22; 
        mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleData);
    }
    
    private function micSampleData(e:SampleDataEvent) {
    
        //store everything sent from the microphone into the array - this will vary in length
        while  (e.data.bytesAvailable > 0) micBuffer.push(e.data.readFloat());
    
        //can wait here for the array to reach a certain size if needed
        if (!playBackSound) {
            playBackSound = new Sound();
            playBackSound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound);
            playBackSound.play();
        }
    }
    
    private function playBackSoundSampleData(e:SampleDataEvent) {
    
        //this number will change depending on the sample rate of microphone
        var numberOfFloats = 8192/8;
        for (var i = 0; i<numberOfFloats && micBuffer.length > 0; i++) 
        {
            _leftChannel[i] = micBuffer.shift();
            count++;
        }
    
        //apply effect
    
        //sample rate here is half of 44 so write twice + twice again to make stereo
        for(var i = 0 ; i < count ; ++i )
        {
            e.data.writeFloat( _leftChannel[i] );
            e.data.writeFloat( _leftChannel[i] );
            e.data.writeFloat( _leftChannel[i] );
            e.data.writeFloat( _leftChannel[i] );
        }
    }