0

我想使用AudioTrack播放 android 的TextToSpeech.synthesizeToFile的输出,但担心我向 AudioTrack 的构建器传递了错误的参数。如果您想亲自查看 TextToSpeech.synthesizeToFile 的输出,我使用 adb 复制了使用 TextToSpeech.synthesizeToFile 生成的文件之一,并将其​​放入此 github 文件中。当我在 linux 中运行时,该文件会播放我写的文本 ( hello world ),并打印以下内容:play tempSoundFile8290688667049742717.wav

play WARN alsa: can't encode 0-bit Unknown or not applicable

tempSoundFile8290688667049742717.wav:

 File Size: 39.4k     Bit Rate: 353k
  Encoding: Signed PCM    
  Channels: 1 @ 16-bit   
Samplerate: 22050Hz      
Replaygain: off         
  Duration: 00:00:00.89  

In:100%  00:00:00.89 [00:00:00.00] Out:19.7k [!=====|=====!]        Clip:0    
Done.

因此,我将 AudioTrack 的参数设置如下:

private AudioDeviceInfo findAudioDevice(int deviceFlag, int deviceType) {
    AudioManager manager = (AudioManager) this.context.getSystemService(Context.AUDIO_SERVICE);
    AudioDeviceInfo[] adis = manager.getDevices(deviceFlag);
    for (AudioDeviceInfo adi : adis) {
        if (adi.getType() == deviceType) {
            return adi;
        }
    }
    return null;
}

AudioDeviceInfo mAudioOutputDevice = findAudioDevice(AudioManager.GET_DEVICES_OUTPUTS,
        AudioDeviceInfo.TYPE_BUS);

AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().
        setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING).
        setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).
        setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
attributes = audioAttributesBuilder.build();

int minBufferSize = AudioTrack.getMinBufferSize(22050, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

AudioTrack.Builder atBuilder = new AudioTrack.Builder();
//builder.setAudioAttributes()
AudioFormat.Builder afBuilder = new AudioFormat.Builder();

afBuilder.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
        .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
        .setSampleRate(22050);

atBuilder.setAudioFormat(afBuilder.build())
        .setTransferMode(AudioTrack.MODE_STREAM)
        .setBufferSizeInBytes(minBufferSize)
        .setAudioAttributes(attributes);


at = atBuilder.build();
at.setPreferredDevice(mAudioOutputDevice);

File myFile = File.createTempFile("tempSoundFile", ".wav");
            myFile.deleteOnExit();
            myFile.setWritable(true);
            myFile.setReadable(true);

然后使用此处的代码播放文件:

/**
* Code taken from here:
* https://stackoverflow.com/questions/7372813/android-audiotrack-playing-wav-file-getting-only-white-noise
*/
private void playWav(){
    Log.d(TAG, "Playing speech to text wav file");
    String filepath = this.myFile.getAbsolutePath();

    int i = 0;
    int BUFFER_SIZE = 512;
    byte[] s = new byte[BUFFER_SIZE];
    try {
        Log.i(TAG, "file path is: " + filepath);
        FileInputStream fin = new FileInputStream(filepath);
        DataInputStream dis = new DataInputStream(fin);


        at.play();

        while((i = dis.read(s, 0, BUFFER_SIZE)) > -1){
            at.write(s, 0, i);
            Log.v(TAG, Arrays.toString(s));

        }
        at.stop();
        at.release();
        dis.close();
        fin.close();

    } catch (FileNotFoundException e) {
        // TODO
        e.printStackTrace();
    } catch (IOException e) {
        // TODO
        e.printStackTrace();
    }
}

当然,正如您在我的代码中看到的那样,对这些的调用分布在不同的异步调用中,但是我已经使用日志语句和调试器调试了所有这些,并且没有发现任何问题。playWav() 在我期望的时候被击中,但没有播放任何东西。

编辑:

我使用 AudioTrack 的主要动机是使其 TextToSpeech 与树莓派语音套件android things 库兼容。使用 AudioTrack 将允许我通过 I2S(或我选择的任何扬声器)播放 textToSpeech。

编辑2,更深入的了解:

根据这个网站,wav 文件有一个 44 字节的标头,说明所有这些参数是什么。在此标题中,位于:

  • 位置 20,指示文件类型的 2 个字节(小端)(PCM 为 16)
  • 位置 22,2 个字节,指示通道数(1 表示单声道,2 表示立体声)(小端序)
  • 位置 24,指示采样率的 4 个字节(小端)
  • 最后在第 34 位,2 个字节指示每个样本的位数(小端序)

这是上述文件的十六进制转储:

$ hd -n 44 tempSoundFile8290688667049742717.wav
00000000 52 49 46 46 f8 99 00 00 57 41 56 45 66 6d 74 20 |RIFF....WAVEfmt |
00000010 10 00 00 00 01 00 01 00 22 56 00 00 44 交流 00 00 |........"V..D...|
00000020 02 00 10 00 64 61 74 61 d4 99 00 00 |....数据....|
0000002c
4

0 回答 0