[Prototyping] Microphone Study #03 リング変調
リング変調でボイスチェンジャーもどき
@author Yukiya Okuda
/**
* Copyright alumican_net ( http://wonderfl.net/user/alumican_net )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/pBxX
*/
package
{
import com.bit101.components.CheckBox;
import com.bit101.components.HUISlider;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Microphone;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.utils.ByteArray;
import flash.utils.getTimer;
/**
* リング変調でボイスチェンジャーもどき
*
* @author Yukiya Okuda
*/
public class Main extends Sprite
{
//----------------------------------------
//CLASS CONSTANTS
private const ZEROS:Point = new Point();
//----------------------------------------
//VARIABLES
/**
* マイクロフォン
*/
private var _mic:Microphone;
/**
* 録音用
*/
private var _records:Vector.<Number>;
/**
* 再生用
*/
private var _sound:Sound;
private var _soundChannel:SoundChannel;
/**
* 録音、再生ヘッダ
*/
private var _position:int;
/**
* 描画用
*/
private var _canvas:BitmapData;
private var _slit:BitmapData;
private var _over:Sprite;
/**
* リング変調用
*/
private var _sample:int;
private var _power:Number;
private var _freq1:Number;
private var _freq2:Number;
private var _useDual:Boolean;
//----------------------------------------
//STAGE INSTANCES
//----------------------------------------
//METHODS
/**
* コンストラクタ
*/
public function Main():void
{
Wonderfl.disable_capture();
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.quality = StageQuality.LOW;
_mic = Microphone.getMicrophone();
_mic.rate = 44;
_mic.setSilenceLevel(0);
_mic.setUseEchoSuppression(true);
_sound = new Sound();
_canvas = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xffffff);
_slit = new BitmapData(1, stage.stageHeight, false, 0xffffff);
addChild( new Bitmap(_canvas) );
_over = addChild( new Sprite() ) as Sprite;
_over.graphics.beginFill(0x0);
_over.graphics.drawRect(0, 0, 100, 100);
_over.graphics.endFill();
_over.blendMode = BlendMode.INVERT;
var freq1Slider:HUISlider = new HUISlider(this, 10, 10, "FREQUENCY 1", function(e:Event):void
{
_freq1 = int( e.currentTarget.value );
});
freq1Slider.minimum = 100;
freq1Slider.maximum = 500;
freq1Slider.value = _freq1 = 300;
var freq2Slider:HUISlider = new HUISlider(this, 10, 30, "FREQUENCY 2", function(e:Event):void
{
_freq2 = int( e.currentTarget.value );
});
freq2Slider.minimum = 500;
freq2Slider.maximum = 900;
freq2Slider.value = _freq2 = 700;
var checkbox:CheckBox = new CheckBox(this, 200, 15, "USE ONLY FREQUENCY 1", function(e:Event):void
{
_useDual = !Boolean( e.currentTarget.selected );
});
_useDual = !(checkbox.selected = false);
_startRecord();
}
/**
* 録音開始
*/
private function _startRecord():void
{
trace("_startRecord");
_over.width = 0;
_position = 0;
_records = new Vector.<Number>(44100 * 5);
_mic.addEventListener(SampleDataEvent.SAMPLE_DATA, _micSampleDataHandler);
}
private function _micSampleDataHandler(e:SampleDataEvent):void
{
var sw:int = stage.stageWidth;
var sh:int = stage.stageHeight;
var datas:ByteArray = e.data;
while (datas.bytesAvailable)
{
var data:Number = _records[_position] = datas.readFloat();
if (_position % 3 == 0)
{
var x:Number = _position / _records.length * sw;
var y:Number = sh * 0.5 - data * 1000;
_canvas.copyPixels(_slit, _slit.rect, new Point(x + 1, 0));
_canvas.setPixel(x, y, 0x0);
}
if (++_position == _records.length)
{
_mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, _micSampleDataHandler);
_startSound();
return;
}
}
}
/**
* 再生開始
*/
private function _startSound():void
{
trace("_startSound");
//リング変調
_power = 6;
_sample = 0;
_position = 0;
_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, _soundSampleDataHandler);
_soundChannel = _sound.play();
}
private function _soundSampleDataHandler(e:SampleDataEvent):void
{
_over.width = stage.stageWidth * (_position / _records.length);
_over.height = stage.stageHeight;
for (var i:int = 0; i < 2048; ++i)
{
var data:Number = _records[_position];
var mod:Number = (_sample / 44100) * (2.0 * Math.PI);
if (_useDual)
{
data *= _power * Math.cos(_freq1 * mod) * Math.cos(_freq2 * mod);
}
else
{
data *= _power * Math.cos(_freq1 * mod);
}
if (++_sample == 44100) _sample = 0;
e.data.writeFloat(data);
e.data.writeFloat(data);
if (++_position == _records.length)
{
_sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, _soundSampleDataHandler);
_startRecord();
return;
}
}
}
}
}