[英]Android Audio Streaming - Getting Static Noise on AudioTrack
我有一個在localhost上運行的流服務器。 當我嘗試從我的Android應用程序流式傳輸音頻時。 我大部分時間都是靜電噪音(你收音機的那種)。 有時完整的音頻是靜態噪音,有時是它的一部分,有時音頻播放得很好,所以我不確定出了什么問題。
這是我的Android應用程序的流代碼:
new Thread(
new Runnable() {
@Override
public void run() {
try {
URI uri = URI.create("http://192.168.1.6:5000/api/tts");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("x-access-token", credentials.getAccessToken());
urlConnection.setRequestProperty("Accept", "*");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream());
String body = "{\"text\": \"" + text + "\", \"ttsLang\": \"" + language + "\"}";
Log.d("TTS_HTTP", body);
osw.write(body);
osw.flush();
osw.close();
Log.d("TTS_OUT", credentials.getAccessToken());
Log.d("TTS_OUT", urlConnection.getResponseCode() + " " + urlConnection.getResponseMessage());
// define the buffer size for audio track
int SAMPLE_RATE = 16000;
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
bufferSize *= 2;
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize*2,
AudioTrack.MODE_STREAM);
byte[] buffer = new byte[bufferSize];
InputStream is = urlConnection.getInputStream();
int count;
audioTrack.play();
while ((count = is.read(buffer, 0, bufferSize)) > -1) {
Log.d("TTS_COUNT", count + "");
audioTrack.write(buffer, 0, count);
}
is.close();
audioTrack.stop();
audioTrack.release();
} catch (IOException e) {
e.printStackTrace();
}
}
}
).start();
請幫我修復代碼來解決問題。 我沒能像前面所描述的那樣正確地聽到聲音。
此外,服務器響應很好,因為我可以使用Python代碼將其保存到文件中。 保存的文件播放得很好。
>>> import requests
>>> import wave
>>> with wave.open("output.wav", "wb") as f:
... f.setframerate(16000) # 16khz
... f.setnchannels(1) # mono channel
... f.setsampwidth(2) # 16-bit audio
... res = requests.post("http://192.168.1.6:5000/api/tts", headers={"x-access-token": token}, json={"text": "Hello, would you like to have some tea", "ttsLang": "en-us"}, stream=True)
... for i in res.iter_content(chunk_size=16*1024):
... f.writeframes(i)
...
更新:將輸入流寫入文件,然后從文件播放到audiotrack工作正常...
最后,我解決了這個問題。 事實證明, AudioTrack
不喜歡寫入不一致的數據量並導致靜態噪聲。 這是正在寫入的字節數序列AudioTrack
之前,這是造成問題的1248
, 3439
, 5152
, 5152
, 3834
,..., 823
(不一致)。 所以,我查看了DataInputStream
的readFully
方法並使用它並修復了靜態噪聲問題。 字節計數順序現在看起來像5152
, 5152
, 5152
,..., 5152
(一致)。 但現在問題是要讀取由於EOFException
而被跳過的剩余字節。 所以我必須實現自己的方法來解決這個問題。
public class TTSInputStream extends DataInputStream {
public TTSInputStream(InputStream in) {
super(in);
}
public final int readFullyUntilEof(byte b[]) throws IOException {
return readFullyUntilEof(b, 0, b.length);
}
public final int readFullyUntilEof(byte b[], int off, int len) throws IOException {
if (len < 0)
throw new IndexOutOfBoundsException();
int n = 0;
while (n < len) {
int count = in.read(b, off + n, len - n);
if (count < 0)
break;
n += count;
}
return n;
}
}
我的最終代碼現在看起來像這樣:
new Thread(
new Runnable() {
@Override
public void run() {
try {
URI uri = URI.create("http://192.168.1.6:5000/api/tts");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("x-access-token", credentials.getAccessToken());
urlConnection.setRequestProperty("Accept", "*");
urlConnection.setChunkedStreamingMode(bufferSize);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream());
String body = "{\"text\": \"" + text + "\", \"ttsLang\": \"" + language + "\"}";
Log.d("TTS_HTTP", body);
osw.write(body);
osw.flush();
osw.close();
Log.d("TTS_OUT", credentials.getAccessToken());
Log.d("TTS_OUT", urlConnection.getResponseCode() + " " + urlConnection.getResponseMessage());
// define the buffer size for audio track
int SAMPLE_RATE = 16000;
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
bufferSize *= 2;
TTSInputStream bis = new TTSInputStream(urlConnection.getInputStream());
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize * 2,
AudioTrack.MODE_STREAM);
byte[] buffer = new byte[bufferSize];
audioTrack.play();
int count;
while ((count = bis.readFullyUntilEof(buffer)) > 0) {
Log.d("TTS_COUNT", "Read " + count + " bytes.");
audioTrack.write(buffer, 0, buffer.length);
}
bis.close();
audioTrack.stop();
audioTrack.release();
} catch (IOException e) {
e.printStackTrace();
}
}
}
).start();
現在我的音頻播放效果不錯,沒有靜音。 希望這可以幫助其他人和我有同樣的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.