FP10.1用 超適当unionボイチャ
マウスダウンの間に録音、放すと送信
/**
* Copyright keno42 ( http://wonderfl.net/user/keno42 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/b4uP
*/
// マウスダウンの間に録音、放すと送信
// forked from keno42's FP10.1用 マイク録音&再生
package
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.SampleDataEvent;
import flash.media.Microphone;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import mx.utils.Base64Decoder;
import mx.utils.Base64Encoder;
import net.user1.reactor.IClient;
import net.user1.reactor.Reactor;
import net.user1.reactor.ReactorEvent;
import net.user1.reactor.Room;
import net.user1.reactor.RoomEvent;
public class VoiceChat extends Sprite
{
private var re:Reactor = new Reactor();
private var r:Room;
private var recording:Sprite = new Sprite();
private const recordR:Number = 100; // 半径
private const recordW:Number = 40; // ボリュームに応じた揺れ幅
private var mic:Microphone;
private var info:TextField = new TextField();
public function VoiceChat()
{
info.autoSize = "left";
info.text = "接続中...";
addChild(info);
re.addEventListener(ReactorEvent.READY, onReady);
re.connect("tryunion.com", 9100);
}
private function onReady(e:ReactorEvent):void {
info.text = "ログイン完了: user" + re.getClientManager().self().getClientID();
r = re.getRoomManager().createRoom("w.vr");
r.addMessageListener("voiceChat", onVoiceChat);
r.addEventListener(RoomEvent.CLIENT_COUNT, onClientCount);
r.join();
addChild(recording);
mic = Microphone.getMicrophone();
mic.rate = 44;
mic.setSilenceLevel(30,2);
mic.setLoopBack(true); // 一度設定でOK押させる
mic.setLoopBack(false);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
private function onClientCount(e:RoomEvent):void {
info.appendText( "\nクライアント数:" + e.getNumClients() );
}
private function onDown(e:MouseEvent):void {
recording.x = e.localX;
recording.y = e.localY;
myVoice = new ByteArray();
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, onRecord);
}
private function onUp(e:MouseEvent):void {
recording.graphics.clear();
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, onRecord);
myVoice.position = 0;
myVoice.compress();
var sendMsg:String = "";
var encoder:Base64Encoder = new Base64Encoder();
encoder.encodeBytes(myVoice);
sendMsg = encoder.flush();
if( sendMsg.length < 100000 ) {
info.appendText( "\n送信: " + sendMsg.length + " bytes" );
r.sendMessage("voiceChat", false, null, sendMsg);
} else {
info.text = "100KB以下のメッセージしか送れません";
}
}
private function onVoiceChat(from:IClient, msg:String):void {
info.appendText( "\n受信: " + msg.length + " bytes, user" + from.getClientID() );
var ba:ByteArray = new ByteArray();
var decoder:Base64Decoder = new Base64Decoder();
decoder.decode(msg);
ba = decoder.flush();
ba.uncompress();
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, function(e:SampleDataEvent):void {
for ( var i:int = 0; i < 8192; i++ ) {
var temp:Number = ( ba.bytesAvailable > 0)?ba.readFloat():0.0;
e.data.writeFloat(temp);
e.data.writeFloat(temp);
}
});
sound.play();
}
private var myVoice:ByteArray = new ByteArray();
private function onRecord(e:SampleDataEvent):void {
myVoice.writeBytes(e.data);
e.data.position = 0;
recording.graphics.clear();
recording.graphics.lineStyle(0);
var fr:Number = recordR + recordW * e.data.readFloat();
var fa:Number = Math.PI / 128;
recording.graphics.moveTo( fr * Math.cos(fa), fr * Math.sin(fa) );
for ( var i:int = 2; i < 256; i += 2 ) {
var r:Number = recordR + recordW * e.data.readFloat();
var a:Number = i * Math.PI / 128;
recording.graphics.lineTo( r * Math.cos(a), r * Math.sin(a) );
}
recording.graphics.lineTo( fr * Math.cos(fa), fr * Math.sin(fa) );
}
}
}