In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

PC-98のBEEP音のアレ forked from: TinySiOPM MML workbench

MML Editor
- shift+Enter で play/stop
- 最下段で再生開始ポジションを指定
------------------------------------------------------------
BGMLIBを移植してみた。でもなんか違う・・・。
本物はBio_100%のサイトで聴けるよ。
// forked from keim_at_Si's TinySiOPM MML workbench
// MML Editor
// - shift+Enter で play/stop
// - 最下段で再生開始ポジションを指定
//------------------------------------------------------------

// BGMLIBを移植してみた。でもなんか違う・・・。
// 本物はBio_100%のサイトで聴けるよ。
package {
	import flash.media.*;
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;

	[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]  
	public class MMLEditor extends Sprite
	{
		private var _sound:Sound;
		private var _channel:SoundChannel;
		private var _module:Beep;
		private var _sequencer:Sequencer;
		
		private var _textField:TextField;
		private var _statusField:TextField;
		private var _position:TextField;
		private var _track:TextField;
		
		function MMLEditor() {
			var format:TextFormat = new TextFormat("MS Gothic", 12, 0x80f0c0);
			_textField = new TextField();
			_textField.width = 465;
			_textField.height = 449;
			_textField.multiline = true;
			_textField.type = "input";
			_textField.defaultTextFormat = format;
			addChild(_textField);
			format.color = 0;
			_statusField= new TextField();
			_statusField.x = 0;
			_statusField.y = 449;
			_statusField.width = 465;
			_statusField.height = 16;
			_statusField.background = true;
			_statusField.backgroundColor = 0x80f0c0;
			_statusField.defaultTextFormat = format;
			_statusField.text = "position:";
			addChild(_statusField);
			_position = new TextField();
			_position.x = 60;
			_position.y = 449;
			_position.type = "input";
			_position.defaultTextFormat = format;
			_position.text = "0";
			addChild(_position);
			stage.addEventListener("keyDown", _onKeyDown);
			
			var mml:String = "";
			mml += ";=======================================\n";
			mml += ";=        爆笑超深どんとこい           =\n";
			mml += ";=        --------------------         =\n";
			mml += ";=        1991 (C) T.Ichikawa          =\n";
			mml += ";=        ALL RIGHTS RESERVED.         =\n";
			mml += ";=======================================\n";
			mml += "T150O2L16N0     ,O2L16N0     ,O3L16N0\n";
			mml += "ERERERERERERERERERERERERERERERER     ,R2GRGRGRGRGRGRGRGRBRBRBRBR     ,R1BRBRBRBR>ERERERER<\n";
			mml += "ERERERERERERERERERERERERERERERERERERERERERERERER     ,BRBRBRBR>ERERERERGRGRGRGRBRBRBRBRBRBRBRBRBRBRBRBR<     ,>GRGRGRGRBRBRBRBR>ERERERERERERERERERERERERERERERER<<\n";
			mml += "L8O2E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,L8N1O5E2.EFF2G.F.D     ,L8N1O4B2.B>CC2D.C.<A\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,E2.EDD1     ,B2.BAA2>>C<B>C16D.<<\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,>E2.EFF2G.F.D<     ,B2.B>CC2D.C.<A\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,>E2.EDD1<     ,B2.BAA1\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,L16GAGF+L8E2REF.A.>CC<B>CD<     ,R1R1\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,>E1E2D4.<A     ,R1R1\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,B2.B>CC1<     ,O4L16GAGF+L8E2REF.A.>CC<B>CD<\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,B1B2A2     ,>E1E2D2<\n";
			mml += "E>E<E>E<G>G<G>G<F+>F+<F+>F+<F>F<F>F<     ,E2G2F+4.F4.G4     ,R1R1\n";
			mml += "E>E<E>E<G>G<G>G<F+>F+<F+>F+<F>F<F>F<     ,E2G2F+4.A4.D4     ,R1R1\n";
			mml += "E>E<E>E<G>G<G>G<F+>F+<F+>F+<F>F<F>F<     ,E2G2F+4.F4.G4     ,B2>E2D4.C4.D4<\n";
			mml += "E>E<E>E<G>G<G>G<A>A<A>A<<B>B<B>B     ,E2G2A4.B4RB4     ,B2>D2E4.E-4R<B4\n";
			mml += "C>C<C>C<C>C<C>C<C>C<C>C<C>C<C>C<     ,>C.<B.E2.>EREREDC<     ,>C.<B.E2.>E2EDC<\n";
			mml += "G>G<G>G<G>G<G>G<G>G<G>G<G>G<G>G<     ,B.A.GG1GRG4     ,B.A.GG1GRG4\n";
			mml += "F>F<F>F<F>F<F>F<F>F<F>F<F>F<F>F<     ,A.G.F2.>CRCRC<BA     ,A.G.F2.>C2C<BA\n";
			mml += "B>B<B>B<B>B<B>B<B>B<B>B<B>B<B>B<     ,B1B2BRB4     ,B1B2BRB4\n";
			mml += "C>C<C>C<C>C<C>C<C>C<C>C<C>C<C>C<     ,>C.<B.E2.>EREREDC<     ,>C.<B.E2.>E2EDC<\n";
			mml += "G>G<G>G<G>G<G>G<G>G<G>G<G>G<G>G<     ,B.A.GG1GRG4     ,B.A.GG1GRG4\n";
			mml += "F+>F+<F+>F+<F+>F+<F+>F+<F+>F+<F+>F+<F+>F+<F+>F+<     ,A.G.F+2.>CRCRCDE<     ,A.G.F+2.>C2CDE<\n";
			mml += "B>B<B>B<B>B<B>B<B>B<B>B<B>B<B>B<     ,>E-2E-<B>E-F+F+1<     ,>E-2E-<B>E-F+F+1<\n";
			mml += "L8O2E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,L8N1O5E2.EFF2G.F.D     ,L8N1O4B2.B>CC2D.C.<A\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,E2.EDD1     ,B2.BAA2>>C<B>C16D.<<\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,>E2.EFF2G.F.D<     ,B2.B>CC2D.C.<A\n";
			mml += "E>E<E>E<E>E<EF4>F<F>F<F>F<F>F<     ,>E2.EDD1<     ,B2.BAA1\n";
			mml += ";<END FLAG>--------------------------------------------------------------------\n";
			_textField.text = mml;
			
			_module = new Beep(2048, _onSoundFrame);
			_sequencer = new Sequencer(_textField.text);
			_sound = new Sound();
			_sound.addEventListener("sampleData", _onStream);
			
			_channel = _sound.play();
		}
		
		private function _onKeyDown(e:KeyboardEvent) : void {
			if (e.shiftKey && e.keyCode == 13) {
				if (_channel) {
					_channel.stop();
					_channel = null;
				} else {
					_module.reset();
					_sequencer.mml = _textField.text;
					_sequencer.pos = int(_position.text);
					_channel = _sound.play();
				}
			}
		}
		
		private function _onSoundFrame() : void {
			_sequencer.onSoundFrame();
		}
		
		private function _onStream(e:SampleDataEvent) : void {
			var moduleOut:Vector.<Number> = _module.render();
			for (var i:int = 0; i<4096; i++) {
				e.data.writeFloat(moduleOut[i]);
			}
		}
	}
}

import flash.events.*;
import flash.utils.*;
import flash.media.*;

class Sequencer
{
	public static var tracks:Array;
	public static var freq:int = 44100;
	public static var tempo:Number = 120;
	public static function get tick():Number {return 7.5 / tempo * freq;}
	
	function Sequencer(mml:String = null)
	{
		this.mml = mml;
	}
	
	public function onSoundFrame() : void {
		for each (var tr:Track in tracks) tr.execute();
		return;
	}
	
	public function set pos(p:int) : void {
		for (var i:int=0; i<p; i++) {
			for each (var tr:Track in tracks) tr.execute();
		}
	}
	
	public function set mml(seq:String) : void
	{
		seq = seq.replace(/[ \t]|;.*$/gm, "");
		
		var list:Array = seq.split("\r");
		var res:Array = new Array("", "", "");
		
		for(var i:int = 0; i < list.length; i++)
		{
			var temp:Array = list[i].split(",");
			for(var t:int = 0; t < temp.length; t++)
			{
				if(t == 3) {break;}
				res[t] += temp[t];
			}
		}
		
		tracks = new Array();
		tracks.push(new Track(res[0]));
		tracks.push(new Track(res[1]));
		tracks.push(new Track(res[2]));
	}
}

class Track
{
	private var codeA:int="A".charCodeAt();
	private var nt:Array=[9,11,0,2,4,5,7];
	private var lentable:Array = new Array();
	private var notelist:Array;
	private var oct:int;
	private var len:int;
	private var tenuto:int;
	private var pos:int;
	private var cnt:Number;
	public var currentNote:Note;
	private var _rex:RegExp=/([A-GRTLON<>])([-+])?(-?\d+)?(\.*\.)?/gi;
	function Track(seq:String)
	{
		lentable[32] = 1;
		lentable[16] = 2;
		lentable[8] = 4;
		lentable[4] = 8;
		lentable[2] = 16;
		lentable[1] = 32;
		
		lentable[24] = 1.5;
		lentable[12] = 3;
		lentable[6] = 6;
		lentable[3] = 12;
		
		var note:Note;
		notelist = new Array();
		
		cnt = 0;
		pos = 0;
		oct = 5;
		len = 4;
		tenuto = 1;
		
		for (var res:* = _rex.exec(seq); res; res = _rex.exec(seq))
		{
			res[1] = res[1].toUpperCase();
			var cmd:int = res[1].charCodeAt();
			if (cmd>=codeA && cmd<=codeA+6)
			{
				note = new Note();
				note.key = nt[cmd-codeA];
				if(res[2] == "-") {note.key--;}
				if(res[2] == "+") {note.key++;}
				note.oct = oct;
				note.len = lentable[(res[3]) ? int(res[3]) : len] * Sequencer.tick;
				if(res[4]) {
					var l:Number = note.len;
					for(var i:int = 0; i < res[4].length; i++)
					{
						l /= 2;
						note.len += l;
					}
				}
				notelist.push(note);
			}
			else if (res[1] == 'R') {
				note = new Note();
				note.key = 0xFF;
				note.oct = 0xFF;
				note.len = lentable[(res[3]) ? int(res[3]) : len] * Sequencer.tick;
				if(res[4]) {
					var l:Number = note.len;
					for(var i:int = 0; i < res[4].length; i++)
					{
						l /= 2;
						note.len += l;
					}
				}
				notelist.push(note);
			}
			else {
				switch(res[1]){
				case 'T': Sequencer.tempo = int(res[3]); break;
				case 'L': len = int(res[3]); break;
				case 'O': oct = int(res[3]); break;
				case 'N': tenuto = int(res[3])break;
				case '<': oct--; break;
				case '>': oct++; break;
				}
			}
		}
		currentNote = notelist[0];
	}
	
	public function execute() : void
	{
		cnt++;
		if (cnt >= currentNote.len)
		{
			cnt -= currentNote.len;
			pos++;
			if(pos == notelist.length) {
				pos = 0;
			}
			currentNote = notelist[pos];
		}
	}
}

class Note
{
	public var key:int;
	public var oct:int;
	public var len:int;
}

class Beep
{
	private var _output:Vector.<Number>;
	private var _bufferSize:int;
	private var _onSoundFrame:Function;
	
	private var phase:Number = 0;
	public var pitch:Number = 0;
	
	function Beep(bufferSize:int=2048, onSoundFrame:Function=null)
	{
		_bufferSize = bufferSize;
		_onSoundFrame = onSoundFrame;
		
		_output = new Vector.<Number>(bufferSize*2, true);
	}
	
	public function reset() : void {
		phase = 0;
	}
	
	public function render():Vector.<Number>
	{
		for (var i:int=0; i < _bufferSize; i++)
		{
			if(_onSoundFrame != null) _onSoundFrame();
			
			var track:Track;
			var num:int;
			if(phase % Sequencer.tick*3 < Sequencer.tick) {
				num = 0;
			}
			else if(phase % Sequencer.tick*3 < Sequencer.tick*2){
				num = 1;
			}
			else {
				num = 2;
			}
			for (var j:int = 0; j < 3; j++)
			{
				track = Sequencer.tracks[num];
				if(track.currentNote.oct != 0xFF) {break;}
				num--;
				if(num == -1) {num = 2;}
			}
			
			if(j==3)
			{
				_output[i*2] = 0;
				_output[i*2+1] = 0;
				phase++;
				continue;
			}
			
			pitch = Math.pow(2, track.currentNote.key / 12) * Math.pow(2, track.currentNote.oct+5) / Sequencer.freq;
			
			_output[i*2] = Math.sin(Math.PI * pitch * phase) < 0 ? 0.1 : -0.1;
			_output[i*2+1] = Math.sin(Math.PI * pitch * phase) < 0 ? 0.1 : -0.1;
			phase++;
		}
		return _output;
	}
}