基于webGl的html5框架说法(二)

浏览器环境下音频类的实现

一套html框架肯定离不开多媒体元素的支持,本例用JavaScript实现在浏览器环境下音频的加载,解码,播放,暂停等功能,代码为了类型判断,和语法检测 都用typescript完成。

1.    音频文件的加载

我们用ajax来加载一个音频文件到浏览器内存中,只需要设置XMLHttpRequest对象的responseType(响应类型)为arraybuffer即刻,示例如下:

// 加载资源
public load(url: string, callBack?:Function) {
   
let self = this;
   
let xhr =<XMLHttpRequest>(window["XMLHttpRequest"] ? new window["XMLHttpRequest"]() : new ActiveXObject("MSXML2.XMLHTTP"));
   
xhr.open("GET", url, true);
   
xhr.responseType = "arraybuffer";
   
xhr.onreadystatechange= () => {
   

    };
   
xhr.send();
}

传入加载的的路径和加载完成的回调函数。

2.    音频文件的解码

利用load函数加载我们可以得到一个buffer,将这个buffer解码才能正常播放这个音频,解码需要我们先有一个音频的上下文环境,如下示例

// 初始化环境
public static initContext() {
   
if (!Sound.audioContext) {
       
Sound.audioContext = new (window["AudioContext"] || window["webkitAudioContext"] || window["mozAudioContext"])();
   
}
}

在sound类中首先需要初始化音频的上下文环境,使用这个audioContext中的decodeAudioData函数可以进行对加载成功的buff进行解码,在ajax的redayState为4后进行解码,如下示例

xhr.onreadystatechange = () => {
    if (xhr.readyState == 4) {
        if (xhr.status >= 400 || xhr.status == 0) {
            alert("加载资源错误!")
        } else {
            // 加载成功 进行解码
            Sound.audioContext.decodeAudioData(xhr.response, (audioBuffer) => {
                self.buffer = audioBuffer;
                self.isLoading = true;
                callBack && callBack();
            }, () => {
                alert("解码失败,路径:" + url);
            })
        }
    }
};

解码成功后将audioBuffer赋值给类就可以了。

3.    实现音频的播放暂停 停止 恢复等功能

音频的播放音量的控制还需要用到一个叫GainNode的对象,这是一个音频处理模块,封装在es的库中,全部代码示例如下:

namespace media {
    export class Sound {
        // 音频环境
        public static audioContext: AudioContext;

        // 初始化环境
        public static initContext() {
            if (!Sound.audioContext) {
                Sound.audioContext = new (window["AudioContext"] || window["webkitAudioContext"] || window["mozAudioContext"])();
            }
        }

        // 音频数据
        public buffer: AudioBuffer;
        // 音频节点控制
        public gain: GainNode;
        // 是否已经加载完成
        public isLoading: boolean = false;
        // 是否正在播放
        public isPlaying: boolean = false;
        // 开始时间
        public startTime: number;
        // 音频资源buffer
        public source: AudioBufferSourceNode;
        // 开始播放时间
        public beginTime: number;
        // 音量
        public _volume: number = 1;
        // 是否暂停
        public isPaused: boolean = true;
        // 音频类型 0为背景音乐 重复播放 1是音效 只播放一次
        public type: number;

        public constructor() {
            this.gain = Sound.audioContext["createGain"] ? Sound.audioContext.createGain() : Sound.audioContext["createGainNode"]();
        }

        // 加载资源
        public load(url: string, callBack?: Function) {
            let self = this;
            let xhr = <XMLHttpRequest>(window["XMLHttpRequest"] ? new window["XMLHttpRequest"]() : new ActiveXObject("MSXML2.XMLHTTP"));
            xhr.open("GET", url, true);
            xhr.responseType = "arraybuffer";
            xhr.onreadystatechange = () => {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 400 || xhr.status == 0) {
                        alert("加载资源错误!")
                    } else {
                        // 加载成功 进行解码
                        Sound.audioContext.decodeAudioData(xhr.response, (audioBuffer) => {
                            self.buffer = audioBuffer;
                            self.isLoading = true;
                            callBack && callBack();
                        }, () => {
                            alert("解码失败,路径:" + url);
                        })
                    }
                }
            };
            xhr.send();
        }


        public play(type: number = 0, volume: number = 1, startTime: number = 0) {
            if (!this.isLoading) {
                alert("未加载成功,播放失败");
                return
            }
            if (this.gain && !this.isPlaying) {
                this.startTime = startTime;
                this.type = type;
                if (this.source) {
                    this.source.onended = null;
                    this.source = null;
                }
                this.source = Sound.audioContext.createBufferSource();
                this.source.buffer = this.buffer;
                this.source.connect(this.gain);
                // 关联音频渲染设备
                this.gain.connect(Sound.audioContext.destination);
                this.source.onended = () => {
                    this.onPlayEnd();
                    if (type == 0) {
                        this.play(type, volume, this.startTime);
                    } else {
                        this.stop();
                    }
                }
                this.beginTime = Date.now();
                this.volume = volume;
                this.source.start(0, this.startTime);
                this.isPlaying = true;
                this.isPaused = false;
                return true;
            }
            return false;
        }

        // 停止
        public stop() {
            if (this.source) {
                if (this.source.stop)
                    this.source.stop(0);
                else
                    this.source["noteOff"](0);
                this.source.onended = null;
                this.source.disconnect();
                this.source = null;
                this.isPlaying = false;
                return true;
            }
            return false;
        }

        // 暂停
        public pause() {
            if (this.source) {
                (<any>this.gain).position = this.position;
                this.isPaused = true;
                return this.stop();
            }
            return false;
        }

        // 播放完成调度
        public onPlayEnd() {

        }

        /**
         * 恢复当前音频
         * @returns {boolean}
         */
        public resume() {
            if (this.gain) {
                return this.play(this.type, this.volume, (<any>this.gain).position);
            }
            return false;
        }

        /**
         * 音量
         * @param {number} value
         */
        public set volume(value: number) {
            if (!this.gain) return;
            this._volume = value;
            this.gain.gain.value = value;
        }

        /**
         * 获取当前播放位置
         * @returns {number}
         */
        public get position() {
            if (this.source)
                return (Date.now() - this.beginTime) / 1000 + this.startTime;
            else
                return 0;
        }
    }
}

最后再来测试下

window.addEventListener("load", () => {
    media.Sound.initContext();
    let sound = new media.Sound();
    sound.load("./mp3/test.mp3", () => {
        sound.play();
    });

}, false);

 

 


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值