主要源码如下

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:mx="library://ns.adobe.com/flex/mx"
                xmlns:sound="com.topyunp.lrceditor.sound.*" xmlns:lrc="com.topyunp.lrceditor.lrc.*"
                width="100%" height="100%" fontFamily="AliShuHei" layout="vertical" paddingBottom="10"
                paddingLeft="10" paddingRight="10" paddingTop="10" fontSize="16">
    <fx:Declarations>
        <sound:SoundPlayer id="player" progress="player_progressHandler(event)"/>
        <lrc:Lrc id="lrc"/>

        <fx:XML id="saveLrcMenuItems">
            <root>
                <menuitem label="GBK" charset="gbk"/>
                <menuitem label="UTF-8" charset="utf-8"/>
            </root>
        </fx:XML>
    </fx:Declarations>

    <fx:Script>
		<![CDATA[
        import com.topyunp.lrceditor.assets.Assets;
        import com.topyunp.lrceditor.dialogs.FileDialog;
        import com.topyunp.lrceditor.utils.StringUtils;
        import com.topyunp.lrceditor.utils.TimeFormatter;

        import mx.controls.Menu;
        import mx.events.MenuEvent;

        [Embed(source="assets/AlimamaShuHeiTi-Bold.otf", embedAsCFF="false", fontName="AliShuHei")]
        private static var AliShuHei:Class;

        [Bindable]
        private var selectedSoundName:String = "";

        [Bindable]
        private var lrcContent:String = "";

        [Bindable]
        private var timeLabel:String = "[00:00]";

        [Bindable]
        private var currentLrcLineContent:String = "";

        protected function btnSelectMp3_clickHandler(event:MouseEvent):void {
            FileDialog.show([new FileFilter("MP3文件", "*.mp3")], function (fileName:String, data:ByteArray):void {
                player.source = data;
                selectedSoundName = fileName;
            });
        }

        protected function btnPlayPause_clickHandler(event:MouseEvent):void {
            if (player.playing) {
                player.pause();
            } else {
                lrc.decode(lrcContent);
                trace(lrc);
                player.play();
            }
        }

        protected function playProgressBar_clickHandler(event:MouseEvent):void {
            player.play((playProgressBar.mouseX / playProgressBar.width) * player.totalTime);
        }

        private function btnInsertTimeLabel_clickHandler(event:MouseEvent):void {
//            trace(lrcContentTextArea.selectionBeginIndex);
            var begin:int = StringUtils.findLineBegin(lrcContent, lrcContentTextArea.selectionBeginIndex - 1);
//            trace("selected begin: " + begin);
            lrcContent = lrcContent.substring(0, begin) + timeLabel + lrcContent.substring(begin);
            var end:int = StringUtils.findLineEnd(lrcContent, begin);
            var nextLineBegin:int = end + 1;
            if (nextLineBegin < lrcContent.length) {
                var nextLineEnd:int = StringUtils.findLineEnd(lrcContent, nextLineBegin);
                if (nextLineEnd >= nextLineBegin && nextLineEnd <= lrcContent.length) {
                    lrcContentTextArea.setSelection(nextLineBegin, nextLineEnd);
//                    trace("select range:", nextLineBegin, nextLineEnd);
                }
            } else {
                lrcContentTextArea.setSelection(0, StringUtils.findLineEnd(lrcContent, 0));
            }
            lrcContentTextArea.setFocus();
        }

        private function player_progressHandler(event:ProgressEvent):void {
            timeLabel = "[" + TimeFormatter.convertMsToMinutesAndSeconds(event.bytesLoaded) + "]";
            var content:String = lrc.getContent(Math.round(event.bytesLoaded / 1000));
            if (content) {
                currentLrcLineContent = content;
            }
        }

        private function btnSaveLrc_clickHandler(event:MouseEvent):void {
            var myMenu:Menu = Menu.createMenu(this, saveLrcMenuItems, false);
            myMenu.labelField = "@label";
            myMenu.addEventListener(MenuEvent.ITEM_CLICK, menuItemHandler);

            var point:Point = new Point(btnSaveLrc.x, btnSaveLrc.y);
            myMenu.show(point.x + 10, point.y + 40);
        }

        private function menuItemHandler(event:MenuEvent):void {
            saveLrc(event.item.@charset);
        }

        private function saveLrc(charset:String = "utf-8"):void {
            var dotPosition:int = selectedSoundName.lastIndexOf(".");
            var fileName:String = null;
            if (dotPosition > -1) {
                fileName = selectedSoundName.substring(0, selectedSoundName.lastIndexOf("."));
            } else {
                fileName = "" + (new Date().getTime());
            }
            fileName += ".lrc";

            var data:ByteArray = new ByteArray();
            data.writeMultiByte(lrcContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), charset);
            data.position = 0;
            var fr:FileReference = new FileReference();
            fr.save(data, fileName);
        }
        ]]>
	</fx:Script>
    <mx:HBox width="100%" verticalAlign="middle">
        <mx:Button focusEnabled="false" label="插入时间 {timeLabel}" id="btnInsertTimeLabel"
                   click="btnInsertTimeLabel_clickHandler(event)"/>
        <mx:Button focusEnabled="false" label="保存LRC" id="btnSaveLrc" click="btnSaveLrc_clickHandler(event)"/>
        <mx:Button focusEnabled="false" id="btnSelectMp3" label="选择歌曲" click="btnSelectMp3_clickHandler(event)"/>
        <mx:Label width="200" text="{selectedSoundName}" fontSize="12" textAlign="center"/>
        <mx:HBox horizontalGap="0">
            <mx:Button id="btnStop" width="24" click="player.stop()" cornerRadius="0"
                       enabled="{player.source!=null}" icon="{Assets.Stop}"/>
            <mx:Button id="btnPlayPause" width="24" click="btnPlayPause_clickHandler(event)"
                       cornerRadius="0" enabled="{player.source!=null}"
                       icon="{player.playing?Assets.Pause:Assets.Play}"/>
        </mx:HBox>
        <mx:ProgressBar id="playProgressBar" width="100%" label="{currentLrcLineContent}"
                        click="playProgressBar_clickHandler(event)" labelPlacement="center"
                        source="{player}"/>
        <mx:Label width="110"
                  text="{TimeFormatter.convertMsToMinutesAndSeconds(playProgressBar.value)}/{TimeFormatter.convertMsToMinutesAndSeconds(playProgressBar.maximum)}"
                  textAlign="right"/>
    </mx:HBox>
    <mx:TextArea focusEnabled="true" width="100%" height="100%" wordWrap="false" id="lrcContentTextArea"
                 text="@{lrcContent}" horizontalScrollPolicy="off"/>
</mx:Application>