【问题标题】:How to calculate available audio frequencies in an array list created from waveform如何计算从波形创建的数组列表中的可用音频频率
【发布时间】:2020-09-10 23:31:03
【问题描述】:

我正在使用歌曲文件来创建 视听 视频,因此我从每一帧中提取音频信息,并且我需要知道我拥有的当前数据块中正在播放哪些频率从当前帧中提取以操作其他内容。

A waveform example obtained with my script

我了解音频波的工作原理,也知道多个频率在同一个声音中的外观(例如上一张表示在音频块末尾带有撞帽的贝司的图像)。但是我无法创建一个函数来估计该波形中的可用频率(存储在一个数组中)。我的大脑现在被炸了。

注意:我在 JavaScript 下工作,我使用 AudioContext 从音频文件中提取信息,但我无法获取频率数据,我只是得到一个波形。我尝试使用AnalyserNode,但是 在我看到的每个教程或文档中,AnalyserNode 需要实时再现音频以获取频率数据,正如我所说,我提取了代表视频每一帧的块,它将在云服务器中工作。

【问题讨论】:

    标签: javascript audio calculation


    【解决方案1】:

    我终于找到了解决方案,如果有人遇到同样的问题,我会回答我自己的问题。请记住,我只想从歌曲文件的每一帧中获取频率(然后获取频谱数据)。所以我不得不停止寻找之前获得的样本数据的频率来采取一些步骤返回(请参阅问题以了解最后一部分)。

    我找到了AudioContext 的替代品OfflineAudioContext。使用 AudioContext,您需要实时播放音频文件以获取频谱数据(音调),但使用 OfflineAudioContext 您可以节省很多时间,因为它通过渲染音频文件尽可能快地处理所有文件数据。我会说WebAudioAPI真的很混乱,我在得到预期的结果后尝试了几次,但我终于得到了。

    您将在下面找到“最终代码”,以获取音频的每一帧(取决于声明的 fps)的频谱数据。此外,您还可以查看下一个数据处理视频结果中获得的数据可以做什么。

    Video Result(抱歉,我无法将视频上传到 StackOverflow,因此您需要从 Google Drive 下载结果视频)

    Javascript

    它将返回每一帧的频谱数据数组。

    [警告] 此代码与 Firefox 不兼容,因为它使用 OfflineAudioContext.pause() 和 OfflineAudioContext.resume() 函数 (see more details)。

    let $audioCtx = new ( window.AudioContext || window.webkitAudioContext )( ) ;
    let $audioOff = null ;
    let $analyser = null ;
    let FFT_SIZE  = 512 ;
    
         fetch( $data.file_url )
              .then( response    => response.arrayBuffer( ) )
              .then( arrayBuffer => $audioCtx.decodeAudioData( arrayBuffer ) )
              .then( async ( audioBuffer ) => {
                window.$audioBuffer = audioBuffer ;
                return new Promise( ( resolve, reject ) => {
                  $audioOff  = new window.OfflineAudioContext( 2, audioBuffer.length, audioBuffer.sampleRate ) ;
                  $analyser  = $audioOff.createAnalyser( ) ;
                  $analyser  . fftSize = FFT_SIZE ;
                  $analyser  . smoothingTimeConstant = $data.fps === 24 ? 0.16 : $data.fps === 29 ? 0.24 : 0.48 ;
                  $analyser  . connect( $audioOff.destination ) ;
                  var source = $audioOff.createBufferSource( ) ;
                      source . buffer = audioBuffer ;
                      source . connect( $analyser ) ;
                  var __data = [ ] ;
                  var fps    = $data.fps || 24 ;
                  var index  = 0.4 ;
                  var length = Math.ceil( audioBuffer.duration * fps ) ;
                  var time   = ( ( 1 / fps ) ) ;
                  var onSuspend = ( ) => {
                    return new Promise( ( res, rej ) => {
                      index  += 1 ;
                      var raw = new Uint8Array( $analyser.frequencyBinCount ) ;
                      $analyser.getByteFrequencyData ( raw ) ;
                      __data.push( raw ) ;
                      if( index < length ) {
                        if( time * ( index + 1 ) < audioBuffer.duration ) 
                          { $audioOff.suspend( time * ( index + 1 ) ).then( onSuspend ) ; }
                        $audioOff.resume( ) ;
                      } return res( 'OK' ) ;
                    } ) ;
                  } ;
                  $audioOff.suspend( time * ( index + 1 ) ).then( onSuspend ) ;
                  source.start( 0 ) ;
                  console.log( 'Decoding Audio-Spectrum...' ) ;
                  $audioOff.startRendering( ).then( ( ) => {
                    console.log( '[✔] Audio-Spectrum Decoded!' ) ;
                    return resolve( __data ) ;
                  } ).catch( ( err ) => {
                    console.log( 'Rendering failed: ' + err ) ;
                    throw { error : 'Get audio data error', message : err } ;
                  } ) ;
                } ) ;
              } )
              .then( async ( spectrumData ) => {
                /* DO SOMETHING WITH SPECTRUM DATA */
                /* spectrumData[ 0 ] is the first frame, depending of established fps */
                /* spectrumData[ 1 ] = 2nd frame ... */
              } ) ;
    

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 2011-03-11
      相关资源
      最近更新 更多