有人可以帮我解决这个问题我有点困惑,我从数据库获取wav数据,我可以设法使用此功能在浏览器上播放这个wav数据:
function playWave(byteArray) {
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var myAudioBuffer = audioCtx.createBuffer(1, byteArray.length, 8000);
var nowBuffering = myAudioBuffer.getChannelData(0);
for (var i = 0; i < byteArray.length; i++) {
nowBuffering[i] = byteArray[i];
}
var source = audioCtx.createBufferSource();
source.buffer = myAudioBuffer;
source.connect(audioCtx.destination);
source.start();
}
一切正常,我只需要一个GUI播放器来播放/暂停/停止并最终绘制频谱。
首先,我尝试使用HTML5的音频标签,但您需要在src参数中放置一个有效的网址:
<audio controls="controls">
Your browser does not support the <audio> tag.
<source src="../m/example.mp3" />
</audio>
是否可以将src参数更改为可以放置和播放字节数组的方法?是否有任何球员可以处理这种情况?我只是想以一定的速率(8000Hz)在播放器(播放/暂停/停止)上播放数据库中的wav,这似乎是一个简单的问题,但我发现没有文章或文档在互联网上谈论它。我在互联网上找到的唯一玩家,你需要提供一个有效的文件。
答案 0 :(得分:0)
我为音频播放对话框制作了一个角度控制器,它是:
App.controller("PlaySoundDialogCtrl", function ($scope, $rootScope, $http, $interval, $mdDialog, $mdMedia, url) {
$scope.url = url;
$scope.error = "";
$scope.audioData = null;
$scope.resampleRate = 44100;
$scope.playing = false;
$scope.source = null;
$scope.buffer = null;
$scope.startedAt = 0;
$scope.pausedAt = 0;
$scope.duration = 0;
$scope.currentTime = 0;
$scope.timeChunks = [];
window.AudioContext = window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext ||
window.oAudioContext ||
window.msAudioContext;
$scope.audioCtx = new AudioContext();
$http.get($scope.url, {responseType: "arraybuffer"}).
success(function(data) {
$scope.audioData = data;
$scope.playByteArray(data);
}).
error(function(data, status) {
$scope.error = "errors.sound-error";
});
$scope.playByteArray = function(byteArray) {
var data = new DataView(byteArray);
var audio = new Int16Array(data.byteLength / Int16Array.BYTES_PER_ELEMENT);
var len = audio.length;
for(var jj = 0; jj < len; ++jj) {
audio[jj] = data.getInt16(jj * Int16Array.BYTES_PER_ELEMENT, true);
}
var mono = new Float32Array(audio.length);
var channelCounter = 0;
for(var i = 0; i < audio.length; ) {
mono[channelCounter] = (audio[i] > 0 ? audio[i]/32767 : audio[i]/-32768);
i = i+1;
channelCounter++;
}
$scope.buffer = $scope.audioCtx.createBuffer(1, mono.length, $scope.resampleRate);
$scope.buffer.getChannelData(0).set(mono);
$scope.duration = $scope.buffer.duration;
for(var i = 0; i < 20; i++) {
$scope.timeChunks.push(($scope.duration/20)*i);
}
window.setTimeout(function() {$scope.play();}, 100);
}
$scope.play = function() {
var offset = $scope.pausedAt;
$scope.source = $scope.audioCtx.createBufferSource();
$scope.source.connect($scope.audioCtx.destination);
$scope.source.buffer = $scope.buffer;
$scope.source.start(0, offset);
$scope.startedAt = $scope.audioCtx.currentTime - offset;
$scope.pausedAt = 0;
$scope.playing = true;
$scope.playInterval = $interval(function() {
$scope.currentTime = $scope.getCurrentTime();
if($scope.currentTime > $scope.duration) {
$scope.stop();
$interval.cancel($scope.playInterval);
$scope.currentTime = 0;
}
}, 500);
}
$scope.timeWatch = $scope.$watch("currentTime", function() {
var all = $(".timeRanger").innerWidth();
var leftOffset = Math.floor(((all-30)/$scope.duration)*$scope.currentTime);
if($(".playerTooltip").length) {
$(".playerTooltip")[0].style.setProperty("left", leftOffset+"px", "important");
}
});
$scope.stop = function() {
if($scope.source != null) {
$scope.source.disconnect();
$scope.source.stop(0);
$scope.source = null;
}
$scope.pausedAt = 0;
$scope.startedAt = 0;
$scope.playing = false;
if(angular.isDefined($scope.playInterval)) $interval.cancel($scope.playInterval);
}
$scope.pause = function() {
var elapsed = $scope.audioCtx.currentTime - $scope.startedAt;
$scope.stop();
$scope.pausedAt = elapsed;
}
$scope.jump = function() {
$scope.pause();
$scope.pausedAt = $scope.currentTime;
$scope.play();
}
$scope.getCurrentTime = function() {
if($scope.pausedAt) {
return $scope.pausedAt;
}
if($scope.startedAt) {
return $scope.audioCtx.currentTime - $scope.startedAt;
}
return 0;
}
$scope.cancel = function() {
$scope.stop();
$mdDialog.cancel();
}
$scope.stopInterval = function() {
if(angular.isDefined($scope.playInterval)) $interval.cancel($scope.playInterval);
}
$scope.$on('$destroy',function() {
if(angular.isDefined($scope.playInterval)) $interval.cancel($scope.playInterval);
if(angular.isDefined($scope.timeWatch)) $scope.timeWatch();
});
}).filter('secToTime', function() {
return function(item) {
var minutes = Math.floor(item/60);
item -= minutes*60;
item = Math.floor(item);
if(item < 10) item = "0"+item;
return minutes+":"+item;
};
});
和视图部分:
<div class="row text-center">
{{currentTime | secToTime}}
<button type="button" class="btn btn-primary" ng-click="pause()" ng-show="playing">Pause</button>
<button type="button" class="btn btn-primary" ng-click="play()" ng-show="!playing">Play</button><br />
<div class="timeRanger">
<input type="range" min="0" max="{{duration}}" step="1" ng-mousedown="stopInterval()" ng-mouseup="jump()" ng-model="currentTime" />
<div class="tooltip playerTooltip top fade in" tooltip-animation-class="fade" style="top: -33px; left: 0;">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">{{currentTime | secToTime}}</div>
</div>
</div>
<!--<button type="button" class="btn btn-primary" ng-click="jump(t)" ng-repeat="t in timeChunks">{{t | secToTime}}</button>-->
</div>
答案 1 :(得分:0)
正确转换byteArray
后,您应该可以使用Blob
。然后,您可以创建一个blob对象URL,并在src
元素上将其设置为source
:
// Create blob from Uint8Array & Object URL.
const blob = new Blob([getByteArray()], { type: 'audio/wav' });
const url = URL.createObjectURL(blob);
// Get DOM elements.
const audio = document.getElementById('audio');
const source = document.getElementById('source');
// Insert blob object URL into audio element & play.
source.src = url;
audio.load();
audio.play();
// Get data from database/server, hardcoded here for simplicity.
function getByteArray() {
const data = [82, 73, 70, 70, 222, 37, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 1, 0, 68, 172, 0, 0, 136, 88, 1, 0, 2, 0, 16, 0, 100, 97, 116, 97, 186, 37, 0, 0, 0, 0, 255, 12, 2, 27, 254, 40, 2, 55, 254, 68, 1, 83, 0, 83, 0, 69, 0, 55, 255, 40, 2, 27, 253, 12, 3, 255, 254, 240, 0, 227, 1, 213, 255, 198, 1, 185, 255, 170, 1, 175, 255, 188, 1, 203, 255, 216, 1, 231, 255, 244, 2, 3, 254, 16];
// Convert byteArray into Uint8Array.
return new Uint8Array(data);
}
<audio controls="controls" id="audio" loop>
Your browser does not support the <audio> tag.
<source id="source" src="" type="audio/wav" />
</audio>
☝️这会在点击时播放声音!