你如何在网络音频api中使用waveshapernode?特别是曲线Float32Array属性?
编辑:清除代码和播放器(在Github上),以便更容易设置频率
我正在尝试使用Karplus Strong字符串合成算法合成字符串,但我无法正确调整字符串.有谁有想法吗?
如上所述,代码在Github上:https://github.com/achalddave/Audio-API-Frequency-Generator(相关位在strings.js).
Wiki有以下图表:

基本上,我产生噪声,然后输出并同时发送到延迟滤波器.延迟滤波器连接到低通滤波器,然后与输出混合.根据维基百科,延迟应该是N个样本,其中N是采样频率除以基频(N = f_s/f_0).
摘自我的代码:
产生噪音(bufferSize是2048,但这不应该太重要)
var buffer = context.createBuffer(1, bufferSize, context.sampleRate);
var bufferSource = context.createBufferSource();
bufferSource.buffer = buffer;
var bufferData = buffer.getChannelData(0);
for (var i = 0; i < delaySamples+1; i++) {
bufferData[i] = 2*(Math.random()-0.5); // random noise from -1 to 1
}
Run Code Online (Sandbox Code Playgroud)
创建延迟节点
var delayNode = context.createDelayNode();
Run Code Online (Sandbox Code Playgroud)
我们需要延迟f_s/f_0样品.但是,延迟节点以秒为单位进行延迟,因此我们需要将其除以每秒的采样数,我们得到(f_s/f_0) / f_s,这就是1/f_0.
var delaySeconds …Run Code Online (Sandbox Code Playgroud) 我目前正在为音乐家开发基于网络的协作录制平台,类似于移植到网络上的基本DAW(具有额外的社交/共享功能).无论如何,我的目标是让它100%无闪存,所以我一直在阅读很多关于HTML5的内容,特别是Web Audio API(这本书有很多帮助,顺便说一下).
要使用getUserMedia()录制用户麦克风的音频,我制作了RecorderJS的自定义版本.简而言之,我将getUserMedia()的输出路由到ScriptProcessorNode,每4096个样本将inputBuffer的内容写入一个稍后导出到PCM WAV文件的数组.到目前为止,它工作正常.
问题是录制过程的开始涉及两件事:播放所有先前录制的曲目,因此音乐家有一个参考播放,并开始实际录制(将缓冲区写入阵列,即).
虽然当用户正在录制时,麦克风的声音没有听得见的延迟或延迟,但是当录制结束并且播放了所有的轨道时,新录制的轨道稍有延迟.
是什么导致这个?有哪些可能的解决方案?
我以为我可以通过将回放发送到同一处理器节点然后找出它们实际开始的时间来找到两个事件之间的时间差,以补偿任何延迟.为此,我需要让ScriptProcessorNode接收通道1和2上的getUserMedia内容,并在通道3和4上播放,但我无法完成这项工作.我尝试将两个源路由到处理器节点,我也尝试使用Merger/Splitter,但似乎没有任何工作.它们都到达通道1和2上的处理器节点,而3和4则为空.
对不起,如果这是偏离主题或不包含实际代码(我很乐意在必要时提供),但是在这个领域没有太多的东西,所以任何想法都会非常受欢迎.
提前致谢!
我创建了audiocontext并将我的麦克风连接到分析仪:
context = new AudioContext();
microphone = context.createMediaStreamSource(stream);
analyser = context.createAnalyser();
analyser.fftSize = 2048;
microphone.connect(analyser);
Run Code Online (Sandbox Code Playgroud)
然后我得到了一些频率数组:
fFrequencyData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(fFrequencyData);
Run Code Online (Sandbox Code Playgroud)
我想在麦克风前播放一些音符,然后显示它是什么音符.我如何获得音符的频率?例如,A1 = 440.00Hz,F#3 = 1480.00Hz.
谢谢!
在使用音频元素(<audio>)或contexts(AudioContext)时,您可以检查它们的currentTime属性以确切了解缓冲区的播放时间。
在我一次创建多个源(或AudioBufferSourceNode)之前,所有这些都是不错的选择AudioContext。
音源可以在不同的时间播放,因此我需要知道它们对应currentTime的,以说明:
一些基础代码供您解决:
buffer1 = [0,1,0]; //not real buffers
buffer2 = [1,0,1];
ctx = new AudioContext();
source1 = ctx.createBufferSourceNode();
source1.buffer = buffer1;
source1.connect(ctx.destination);
source1.start(0);
source2 = ctx.createBufferSourceNode();
source2.buffer = buffer2;
source2.connect(ctx.destination);
setTimeout(1000/*some time later*/){
source2.start(0);
}
setTimeout(1500/*some more time later*/){
getCurrentTime();
}
function getCurrentTime(){
/* magic */
/* more magic */
console.log("the sources currentTime values are obviously 1500 (source1) and 500 (source2).");
}
Run Code Online (Sandbox Code Playgroud) 我问了一个类似于此前的问题,但它没有解决我的问题并且解释得很差.这次我做了插图,希望能更好地解释.
我的音频播放器有一个简单的频谱分析仪.频率存储在每个都更新的数组中requestAnimationFrame,数组如下所示:
fbc_array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(fbc_array);
Run Code Online (Sandbox Code Playgroud)
在这里阅读更多关于getByteFrequencyData的信息.
所以这个工作正常,但我希望频率在整个频谱中均匀分布.现在它显示线性频率:
正如您所看到的,这里的主要频率范围是高音(高端),最主要的频率范围是低音范围(低端).我希望我的分析仪具有均匀分布的频率范围,如下所示:
在这里,您可以看到分析仪上均匀分布的频率.这可能吗?
我用于生成分析器的代码如下所示:
// These variables are dynamically changed, ignore them.
var canbars = 737
var canmultiplier = 8
var canspace = 1
// The analyser
var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x,
bar_width, bar_height;
function audioAnalyserFrame() {
'use strict';
var i;
canvas.width = $('analyser-').width();
canvas.height = $('analyser-').height();
ctx.imageSmoothingEnabled = false;
fbc_array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(fbc_array);
ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
ctx.fillStyle = "white"; …Run Code Online (Sandbox Code Playgroud) 我正在构建一个显示有关视频音频的信息的组件。我使用AudioContext接口从 HTML5 视频元素获取音频样本。第一次创建组件时它工作正常,但是当卸载组件然后在稍后重新创建时,我收到以下错误消息:
未捕获的 InvalidStateError:无法在“AudioContext”上执行“createMediaElementSource”:HTMLMediaElement 之前已连接到不同的 MediaElementSourceNode。
这是我获取音频的方式:
const video = document.querySelectorAll('video')[0]
if (!window.audioContext) {
window.audioContext = new (window.AudioContext || window.webkitAudioContext)
}
if (!this.source && !this.scriptNode) {
this.source = window.audioContext.createMediaElementSource(video)
this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
}
this.scriptNode.onaudioprocess = (evt) => {
// Processing audio works fine...
}
this.source.connect(this.scriptNode)
this.scriptNode.connect(window.audioContext.destination)
Run Code Online (Sandbox Code Playgroud)
当组件被卸载时,我会这样做:
if (this.source && this.scriptNode) {
this.source.disconnect(this.scriptNode)
this.scriptNode.disconnect(window.audioContext.destination)
}
Run Code Online (Sandbox Code Playgroud)
我认为这会让我处于可以安全地创建和连接新节点的状态。但是下次挂载组件时,这个块会抛出前面提到的错误:
if (!this.source && !this.scriptNode) {
this.source = window.audioContext.createMediaElementSource(video) // this throws the error
this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
} …Run Code Online (Sandbox Code Playgroud) 如何缩短(从前面)一组音频 blob 并仍然具有可播放的音频。
我最终尝试使用 JS MediaRecorder API录制连续 45 秒的音频循环。用户将能够按下按钮,最后 45 秒的音频将被保存。我可以很好地录制、播放和下载单个录音。
当我有一个chunks来自 MediaRecorder的数组称为1000 个 blob 并使用chunks.slice(500, 1000)生成的 blob 数组时,不能用于播放或下载音频。
奇怪的是chunks.slice(0,500)仍然可以正常工作。
let chunks = [];
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
}
// At some later time, attempt to trim
const trimmedAudio = chunks.slice(500, 1000)
const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
const audioURL = URL.createObjectURL(blob); …Run Code Online (Sandbox Code Playgroud) javascript typed-arrays arraybuffer mediarecorder web-audio-api
我想进行录音,从不同的 mediaStream 对象(其中一些,远程)获得多个音轨。使用 getAudioTracks() 方法并使用 addTrack() 将它们添加到 mediaStream 对象。在将最后一个对象作为 mediaRecorder 的参数传递时,我意识到它只记录位于 [0] 位置的音轨。这让我明白 mediaRecorder 能够按类型录制曲目,有没有办法将这些曲目合并为一个曲目以使用 mediaRecorder 正确录制它们?如果可能并且如果它存在,我将不胜感激任何解释这一点的页面
我们目前正在开发一个网站,该网站允许用户播放连接到audiocontext的简单音频标签。我们知道IOS的技术问题,例如由用户手势启动的播放。一切正常,直到IOS12。既然IOS13已经发布,那么什么也无法工作了。
它适用于所有台式机,Android和IOS(最高IOS13)。
有什么想法吗?
使用连接到iPhone的Desktop上的Safari进行调试时,控制台中没有错误消息。
https://codepen.io/gchad/pen/WNNvzzd
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<body>
<div>
<h1>Play Audio Tag connected to audio context</h1>
<div id="playbutton" style="width:100px; height:100px; background:blue; color:white; margin:auto; text-align: center; font-size: 30px; cursor: pointer;">
Play
</div>
<audio id="myPlayer" crossorigin="anonymous" >
<source src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/858/outfoxing.mp3"/>
<!--http://commondatastorage.googleapis.com/codeskulptor-assets/week7-brrring.m4a-->
</audio>
</div>
<script>
var player = document.getElementById('myPlayer'),
playbutton = document.getElementById('playbutton'),
playStatus = 'paused';
var audioContext = new(window.AudioContext || window.webkitAudioContext)();
var audioSource = audioContext.createMediaElementSource(player);
audioSource.connect(audioContext.destination);
playbutton.addEventListener('click',function(ev){
if( playStatus == 'paused'){
audioContext.resume();
player.play();
playbutton.innerHTML = "Pause";
playStatus = 'isPlaying'; …Run Code Online (Sandbox Code Playgroud) web-audio-api ×10
javascript ×7
audio ×3
html5-audio ×3
html5 ×2
api ×1
arraybuffer ×1
getusermedia ×1
html ×1
ios13 ×1
typed-arrays ×1
webkit ×1
webrtc ×1