Search code examples
flashmp3

Free alternative to SoundBooth for adding cue-points into MP3 for Flash?


Is there a free alternative to Soundbooth for adding cue-points to audio tracks for use in Flash? I seem to remember that you can add them to the file itself (I think). I know you can do this with FLV.

Just checking before I buy SB..


Solution

  • There must be some free app out there, but what you're trying to do is somewhat simple. I just whipped together a simple 'app' for you. I say app, it's actually a swf which allows to do the following:

    1. Load an MP3 File
    2. Scrub through it
    3. Add/remove/drag markers
    4. Export FLV cue points for those markers

    Here's how you use it:

    • Double Click the stage to load an mp3
    • Click and Drag to scrub through - a black line will appear as a 'playhead'
    • ALT+Click to add a marker, which you can then drag around
    • Shift+Click to remove a marker
    • Shift+Double Click to get the cue points in your clipboard. The sound will stop playing as a confirmation.

    You can resize the swf for a larger scrub area.

    This is the most basic approach I could come with right now, not very fancy, not very clean, but it should do the job. Also, you can extend this as you like, adjust the xml/output/etc.

    All you need to do is grab FlexibleFactory's audiofx Library, which I use to load an MP3 from FileReference and compile the code bellow:

    package {
        import org.audiofx.mp3.MP3FileReferenceLoader;
        import org.audiofx.mp3.MP3SoundEvent;
    
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Rectangle;
        import flash.media.Sound;
        import flash.media.SoundChannel;
        import flash.net.FileFilter;
        import flash.net.FileReference;
        import flash.system.System;
        /**
         * @author George Profenza
         */
        public class MiniMark extends Sprite{
    
            private var w:Number,h:Number,pos:Number;
            private var pressed:Boolean = false;
            private var file:FileReference;
            private var formats:FileFilter;
            private var sound:Sound;
            private var channel:SoundChannel;
            private var dragRect:Rectangle;
            private var markers:Vector.<Sprite>;
    
            public function MiniMark(){
                init();
            }   
            private function init():void {
                stage.align = StageAlign.TOP_LEFT;
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.doubleClickEnabled = true;
                w = stage.stageWidth;
                h = stage.stageHeight;
                dragRect = new Rectangle(0, 0, w, 0);
                markers = new Vector.<Sprite>();
    
                file = new FileReference();
                file.addEventListener(Event.SELECT, fileSelected);
                formats = new FileFilter("MP3s (*.mp3)","*.mp3"); 
    
                sound = new Sound();
    
                stage.addEventListener(MouseEvent.MOUSE_DOWN, onPress);
                stage.addEventListener(MouseEvent.MOUSE_UP, onRelease);
                stage.addEventListener(MouseEvent.DOUBLE_CLICK, selectFile);
                stage.addEventListener(Event.RESIZE, onResize);
                this.addEventListener(Event.ENTER_FRAME, update);
            }
    
            private function onResize(event : Event) : void {
                w = stage.stageWidth;
                h = stage.stageHeight;
                dragRect.width = w;
            }
    
            private function selectFile(event : MouseEvent) : void {
                if(event.shiftKey) exportCues();
                else             file.browse([formats]);
            }
    
            private function exportCues() : void {
                var values : Array = [];
                for (var i : int = 0 ; i < numChildren; i++) values[i] = markers[i].x;
                values.sort(Array.NUMERIC);
                var cues : XML = <FLVCoreCuePoints Version="1" />;
                for (i = 0 ; i < numChildren; i++) {
                    cues.appendChild(<CuePoint><Time /><Type>event</Type><Name /></CuePoint>);
                    cues.CuePoint[i].Name.appendChild("Marker"+(i+1));
                    cues.CuePoint[i].Time.appendChild((values[i] / w) * sound.length);
                }
                trace(cues.toXMLString());
                System.setClipboard(cues.toXMLString());
                if(channel) channel.stop();
            }
            private function fileSelected(event : Event) : void {
                var mp3loader:MP3FileReferenceLoader = new MP3FileReferenceLoader();
                    mp3loader.addEventListener(MP3SoundEvent.COMPLETE,soundReady);
                    mp3loader.getSound(file);
            }
    
            private function soundReady(event : MP3SoundEvent) : void {
                sound = event.sound;
            }
            private function onPress(event : MouseEvent) : void {
                pressed = true;
                if (event.altKey && channel) addMarker();
            }
    
            private function onRelease(event : MouseEvent) : void {
                pressed = false;
                dropMarkers(event);
            }
    
            private function update(event : Event) : void {
                if (pressed){
                    if (sound.length) {
                        if (channel) channel.stop();
                        channel = sound.play(sound.length * (mouseX/w));
                    }
                }
                drawPlayhead();
            }
            private function drawPlayhead():void{
                graphics.clear();
                graphics.lineStyle(1);
                pos = mouseX;
                if (!pressed && channel) pos = (channel.position / sound.length) * w;  
                graphics.moveTo(pos, 0);
                graphics.lineTo(pos,h); 
            }
    
            private function addMarker():Sprite{
                var marker : Sprite = new Sprite();
                marker.graphics.beginFill(0x009900,.5);
                marker.graphics.drawRect(-1, 0, 2, h);
                marker.graphics.endFill();
                marker.x = mouseX;
                marker.buttonMode = true;
                marker.addEventListener(MouseEvent.MOUSE_DOWN, dragMarker);
                addChild(marker);
                markers.push(marker);
                return marker;
            }
            private function removeMarker(marker:Sprite):void{
                for (var i:int = 0 ; i < numChildren ; i++) {
                    if (markers[i] == marker) {
                        markers.splice(i, 1);
                        removeChildAt(i);
                    }
                }   
            }
            private function dragMarker(event : MouseEvent) : void {
                if(event.shiftKey) removeMarker(event.currentTarget as Sprite);
                else              event.currentTarget.startDrag(false, dragRect);
            }
    
            private function dropMarkers(event : MouseEvent) : void {
                for (var i : int = 0 ; i < numChildren; i++) markers[i].stopDrag();     
            }
    
        }
    }
    

    HTH