Я хочу воспроизвести вывод Android TextToSpeech.synthesizeToFile , используя AudioTrack , но боюсь, что я передаю сборщикам AudioTrack неправильные параметры. Я скопировал один из файлов, созданных с помощью TextToSpeech.synthesizeToFile, используя adb, и вставил этот файл github , если вы хотите увидеть вывод TextToSpeech.synthesizeToFile для себя. Когда я запускаю play tempSoundFile8290688667049742717.wav
в Linux, файл воспроизводит текст, который я написал ( hello world ), и печатает следующее:
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:
* /7213439/android-audiotrack-vosproizvodit-wav-fail-poluchaya-tolko-belyi-shum
*/
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 с голосовым набором raspberry pi библиотека вещей для Android . Использование AudioTrack позволит мне воспроизводить textToSpeech через I2S (или любой другой динамик, который я выберу).
редактировать 2, более глубокий взгляд:
Согласно этому веб-сайту , wav-файлы имеют 44-байтовый заголовок, который сообщает обо всех этих параметрах. В этом заголовке по адресу:
- позиция 20, 2 байта, которые определяют тип файла (little-endian) (16 для PCM)
- позиция 22, 2 байта, которые определяют количество каналов (1 для моно, 2 для стерео) (младший порядок)
- позиция 24, 4 байта, которые определяют частоту дискретизации (little-endian)
- и, наконец, в позиции 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 <b>00 01 00 01 00 22 56</b> 00 00 44 ac 00 00 |........"V..D...|
00000020 02 <b>00 10</b> 00 64 61 74 61 d4 99 00 00 |....data....|
0000002c