package { import flash.display.Bitmap; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; import flash.events.ProgressEvent; import flash.events.SampleDataEvent; import flash.geom.Point; import flash.media.Sound; import flash.net.FileReference; import flash.net.URLRequest; import flash.text.TextField; import flash.text.TextFormat; import flash.utils.ByteArray; /** * TO DO : * * -ajouter chargement d'un mp3 local (avec libraririe de spencer) * OK -ajouter rendu graphique de platine qui tourne (rotationY :) * OK -ajouter des contrôles (on/off, pitch); * -mettre un doigt * OK -interpoler les valeurs pour tenter d'avoir quelque chose... ???? * oui-se poser des questions sur la granularité * **/ [SWF(width='850',height='450',backgroundColor='0x000000',frameRate='40')] public class ExampleMP3ExtractAndCopy extends Sprite { private var _mp3Loader:Sound; private var _outputSound:Sound; private var _samplesData:ByteArray; private var _position:Number; private var _speed:Number; private var _pitchValue:Number; private var _pitchZeroPos:Number; private var _pitchOffset:Number; private var _numSamples:int; private var _range:Number; private var _field:TextField; private var _buttonPressed:Boolean; private var _pMouseX:Number; private var _mouseDiff:Number; private var _file:FileReference; private var _vinyl:Sprite; private var _pitch:Sprite; private var _centerX:Number; private var _centerY:Number; private var _container:Sprite; public function ExampleMP3ExtractAndCopy() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; _numSamples = 2048; _position = 0; _speed = 1; _range = 8; _pitchValue = 1; _buttonPressed = false; _container = new Sprite(); _container.rotationX = -30; addChild(_container); var v:Bitmap = new PlatineAsset(); v.x = -171; v.y = -168; _container.addChild( v ); _vinyl = new Sprite(); v = new DiscAsset(); v.x = - v.width / 2; v.y = - v.height / 2; _vinyl.addChild( v ); _vinyl.buttonMode = true; _container.addChild( _vinyl ); _pitch = new Sprite(); _pitch.addChild( new PitchAsset() ); _pitch.x = 396-171; _pitch.y = _pitchZeroPos = 228-168; _pitch.buttonMode = true; _pitch.addEventListener( MouseEvent.MOUSE_DOWN, onPitchMouseDown ); _container.addChild( _pitch ); stage.addEventListener( Event.RESIZE, onStageResize ); onStageResize(); _field = new TextField(); _field.defaultTextFormat = new TextFormat( 'Arial', 14, 0xFFFFFF ); _field.x = 20; _field.y = 20; _field.width = 400; _field.selectable = false; _field.mouseEnabled = false; _field.text = 'LOADING SOUND'; addChild(_field); loadMp3(); } private function onStageResize(event:Event = null):void { _centerX = stage.stageWidth / 2; _centerY = stage.stageHeight / 2; _container.x = _centerX; _container.y = _centerY; this.transform.perspectiveProjection.projectionCenter = new Point( _centerX, _centerY); } private function loadMp3():void { _mp3Loader = new Sound(); _mp3Loader.addEventListener( Event.COMPLETE, onMp3Loaded ); _mp3Loader.addEventListener( ProgressEvent.PROGRESS, onMp3LoadProgress ); _mp3Loader.load( new URLRequest( 'sound.mp3' ) ); } private function onMp3LoadProgress(event:ProgressEvent):void { _field.text = 'LOADING SOUND [ ' + int(event.bytesLoaded / event.bytesTotal*100) + '% ]'; } private function onMp3Loaded(event:Event):void { _field.text = 'UNPACKING SOUND'; _samplesData = new ByteArray(); _mp3Loader.extract( _samplesData, 99999999 ); _mp3Loader.removeEventListener( Event.COMPLETE, onMp3Loaded ); _mp3Loader.removeEventListener( ProgressEvent.PROGRESS, onMp3LoadProgress ); _mp3Loader = null; addEventListener( Event.ENTER_FRAME, onUpdateDisplay ); _vinyl.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown ); stage.addEventListener( MouseEvent.MOUSE_UP, onMouseUp ); _outputSound = new Sound(); _outputSound.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleDataRequired ); _outputSound.play(); } private function onMouseDown(event:MouseEvent):void { _buttonPressed = true; _pMouseX = Math.atan2(mouseY - _centerY, mouseX - _centerX); _mouseDiff = 0; } private function onMouseUp(event:MouseEvent):void { _buttonPressed = false; } private function onPitchMouseDown(event:MouseEvent = null):void { _pitchOffset = mouseY; addEventListener( Event.ENTER_FRAME, onPitchDrag ); stage.addEventListener( MouseEvent.MOUSE_UP, onPitchMouseUp ); event.stopImmediatePropagation(); } private function onPitchMouseUp(event:MouseEvent = null):void { removeEventListener( Event.ENTER_FRAME, onPitchDrag ); stage.removeEventListener( MouseEvent.MOUSE_UP, onPitchMouseUp ); event.stopImmediatePropagation(); } private function onPitchDrag(event:Event):void { var ny:Number = mouseY; _pitch.y += ny-_pitchOffset; if (_pitch.y<_pitchZeroPos-50) _pitch.y=_pitchZeroPos-50; if (_pitch.y>_pitchZeroPos+50) _pitch.y=_pitchZeroPos+50; _pitchOffset = ny; _pitchValue = 1 + (_pitchZeroPos - _pitch.y)*.008; } private function onSampleDataRequired(event:SampleDataEvent):void { var i:int; var nMouseX:Number = mouseX; var intPos:int, decPos:Number, valL1:Number, valL2:Number, valR1:Number, valR2:Number; // scratch // _speed = ( ( mouseX - stage.stageWidth / 2 ) / stage.stageWidth * _range); // slow if (_buttonPressed) { if (_mouseDiff) { _speed += (_mouseDiff - _speed)*.6; } else { _speed *= .7; } } else { _speed += (_pitchValue-_speed)*.3; } if (_speed>=1) { // lecture séquencielle simple et répétitive for( i=0;i<_numSamples;i++) { _samplesData.position = int(_position) * 8; event.data.writeDouble( _samplesData.readDouble() ); _position += _speed; } } else { // interpolation for( i=0;i<_numSamples;i++) { intPos = int(_position); decPos = _position - intPos; _samplesData.position = intPos * 8; valL1 = _samplesData.readFloat(); valR1 = _samplesData.readFloat(); valL2 = _samplesData.readFloat(); valR2 = _samplesData.readFloat(); event.data.writeFloat( valL1 * decPos + valL2 * (1-decPos) ); event.data.writeFloat( valR1 * decPos + valR2 * (1-decPos) ); _position += _speed; } } } private function onUpdateDisplay(event:Event):void { if (_buttonPressed) { var na:Number = Math.atan2(mouseY - _centerY, mouseX - _centerX); //if ( na > _pMouseX + Math.PI ) na -= 2*Math.PI; if ( na > _pMouseX + Math.PI ) na -= 2*Math.PI; else if ( na < _pMouseX - Math.PI) na += 2*Math.PI; _field.text = 'pROT : \t\t' + _pMouseX + '\nROT : \t' + na; _mouseDiff = (_mouseDiff * .4) + ((na - _pMouseX) * 8); _pMouseX = na; } _vinyl.rotation += _speed / Math.PI * 12; //_field.text = 'SPEED : \t\t' + _speed + '\nPOSITION : \t' + int(_position/44100); } /* private function loadLocalFile(event:MouseEvent):void { _file = new FileReference(); _file.addEventListener( Event.SELECT, onFileSelected ); _file.addEventListener( Event.COMPLETE, onFileLoaded ); _file.browse( [ new FileFilter( 'MP3 Audio File', '*.mp3;*.MP3' ) ] ); } private function onFileSelected(event:Event):void { _file.load(); } private function onFileLoaded(event:Event):void { //var s:Sound = new Sound(); } */ [Embed(source='assets/disc.gif')] private var DiscAsset:Class; [Embed(source='assets/pitch.png')] private var PitchAsset:Class; [Embed(source='assets/platine.jpg')] private var PlatineAsset:Class; } }