【问题标题】:Distorted audio in iOS 7.1 with WebAudio APIiOS 7.1 中带有 WebAudio API 的音频失真
【发布时间】:2015-07-06 06:00:51
【问题描述】:

在 iOS 7.1 上,使用 Web Audio API 播放音频时,我不断收到嗡嗡声/嘈杂/失真的声音。听起来是distorted like this,而不是normal like this

使用 HTML5 音频时可以使用相同的文件。在桌面(Firefox、Chrome、Safari)上一切正常。

编辑:

  • iOS 模拟器版本 iOS 7.1、8.1、8.2 中的音频失真。嗡嗡声经常在我播放任何内容之前就开始了。
  • 在 Chrome 和 Safari 中运行 iOS 7.1 的物理 iPhone 上的音频失真。
  • 在 Chrome 和 Safari 中运行 iOS 8.1 的物理 iPhone 上的音频效果很好。

即:嗡嗡声在 iOS 7.1 上。只要。


Howler.js 不是问题。像这样使用纯 JS 的问题仍然存在:

var context;
var sound;
var extension = '.' + ( new Audio().canPlayType( 'audio/ogg' ) !== '' ? 'ogg' : 'mp3');


/** Test for WebAudio API support **/
try {
    // still needed for Safari
    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    // create an AudioContext
    context = new AudioContext();
} catch(e) {
    // API not supported
    throw new Error( 'Web Audio API not supported.' );
}

function loadSound( url ) {
    var request = new XMLHttpRequest();
    request.open( 'GET', url, true );
    request.responseType = 'arraybuffer';

    request.onload = function() {
        // request.response is encoded... so decode it now
        context.decodeAudioData( request.response, function( buffer ) {
        sound = buffer;
        }, function( err ) {
            throw new Error( err );
        });
    }

    request.send();
}

function playSound(buffer) {
    var source = context.createBufferSource();
    source.buffer = buffer;
    source.connect(context.destination);
    source.start(0);
}

loadSound( '/tests/Assets/Audio/En-us-hello' + extension );


$(document).ready(function(){ 

    $( '#clickme' ).click( function( event ) {
        playSound(sound);
    });


}); /* END .ready() */

此代码的实时版本可在此处获得:Web Audio API - Hello world


Google 并未针对 iOS 7.1 上的此类失真问题提出任何结果。

还有其他人遇到过吗?我应该向 Apple 提交错误报告吗?

【问题讨论】:

  • 您是否对其他音频文件或只是那个文件有同样的问题?我在装有 iOS 8.3 的 iPhone 上测试了你的现场演示,没有听到任何失真。
  • 是的,它发生在不同的文件中。这是另一个更高级别的测试:bilingueanglais.com/tmp/howler/v2-howler-hello.html Chrome 很好,只有 Safari 有问题。
  • 这看起来像是一个低级的 Safari 问题。查看您记录的波形,每 512 个样本中大约有 90 个样本为零 - 就像它们的块处理或解码出现问题一样。
  • 这仍然是 iOS 9.2 的问题。
  • 这里有同样的问题(在 iPhone 5 (IOS 9.2) 和两个不同的 iPhone 6(IOS 9.2 和 IOS 9.2.1)上测试。无法在 iPhone 5S (IOS 9.2.1) 上重现该问题). 模式似乎是它第一次工作,并且总是在重新加载后。但是如果我关闭/重新打开 Safari,声音总是第一次失真,并且在重新加载后工作。

标签: ios audio mobile-safari web-audio-api


【解决方案1】:

我认为该问题是由于重置 audioContext.sampleRate 属性引起的,这似乎发生在浏览器/操作系统播放以不同采样率记录的内容之后。

我设计了以下解决方法,它基本上以设备当前播放的采样率无声地播放一个短 wav 文件:

"use strict";

var getData = function( context, filePath, callback ) {
    var source = context.createBufferSource(),
        request = new XMLHttpRequest();

    request.open( "GET", filePath, true );

    request.responseType = "arraybuffer";

    request.onload = function() {
        var audioData = request.response;

        context.decodeAudioData(
            audioData,
            function( buffer ) {
                source.buffer = buffer;

                callback( source );
            },
            function( e ) {
                console.log( "Error with decoding audio data" + e.err );
            }
        );
    };

    request.send();
};

module.exports = function() {
    var AudioContext = window.AudioContext || window.webkitAudioContext,
        context = new AudioContext();

    getData(
        context,
        "path/to/short/file.wav",
        function( bufferSource ) {
            var gain = context.createGain();
            gain.gain.value = 0;
            bufferSource.connect( gain );
            gain.connect( context.destination );
            bufferSource.start( 0 );
        }
    );
};

显然,如果某些设备具有不同的采样率,则您需要针对每种采样率检测和使用特定文件。

【讨论】:

    【解决方案2】:

    iOS6+ Safari 的默认采样率为 48000。如果您在第一次打开移动版 Safari 时将其输入开发者控制台,您将获得 48000:

    var ctx = new window.webkitAudioContext();
    console.log(ctx.sampleRate);
    

    进一步参考:https://forums.developer.apple.com/thread/20677

    然后,如果您在加载时关闭初始上下文:ctx.close(),下一个创建的上下文将使用大多数其他浏览器使用的采样率 (44100),并且声音将播放而不会失真。

    感谢这为我指明了正确的方向(以防上述方法在将来不再有效):https://github.com/Jam3/ios-safe-audio-context/blob/master/index.js

    截至发布日期的功能:

    function createAudioContext (desiredSampleRate) {
      var AudioCtor = window.AudioContext || window.webkitAudioContext
    
      desiredSampleRate = typeof desiredSampleRate === 'number'
        ? desiredSampleRate
        : 44100
      var context = new AudioCtor()
    
      // Check if hack is necessary. Only occurs in iOS6+ devices
      // and only when you first boot the iPhone, or play a audio/video
      // with a different sample rate
      if (/(iPhone|iPad)/i.test(navigator.userAgent) &&
          context.sampleRate !== desiredSampleRate) {
        var buffer = context.createBuffer(1, 1, desiredSampleRate)
        var dummy = context.createBufferSource()
        dummy.buffer = buffer
        dummy.connect(context.destination)
        dummy.start(0)
        dummy.disconnect()
    
        context.close() // dispose old context
        context = new AudioCtor()
      }
    
      return context
    }
    

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • 编辑了更详细的解释和来自原始链接的代码 sn-p
    • 不幸的是,这个答案在 iOS 12 中对我不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多