|
|
|
@ -822,39 +822,77 @@ class AzureAsrHelper(private val context: Context) { |
|
|
|
|
|
|
|
// 3. 单独封装线程启动逻辑 |
|
|
|
fun startCaptureThread() { |
|
|
|
// 开始录音 |
|
|
|
audioRecord?.startRecording() |
|
|
|
captureThread = Thread { |
|
|
|
// 根据实际采样率计算缓冲区大小 |
|
|
|
val supportedSampleRates = intArrayOf(16000, 8000, 11025, 22050, 44100) |
|
|
|
var bufferSize = 0 |
|
|
|
// 查找设备支持的最佳采样率 |
|
|
|
val sampleRate = supportedSampleRates.firstOrNull { rate -> |
|
|
|
bufferSize = AudioRecord.getMinBufferSize( |
|
|
|
rate, |
|
|
|
AudioFormat.CHANNEL_IN_MONO, |
|
|
|
AudioFormat.ENCODING_PCM_16BIT |
|
|
|
) |
|
|
|
bufferSize > 0 // 返回正值表示支持 |
|
|
|
} ?: 16000 // 默认回退值 |
|
|
|
|
|
|
|
val buffer = ByteArray(bufferSize) |
|
|
|
|
|
|
|
while (!Thread.interrupted() && audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) { |
|
|
|
if (!isPaused) { |
|
|
|
// 读取音频 |
|
|
|
val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0 |
|
|
|
if (bytesRead > 0) { |
|
|
|
try { |
|
|
|
// 确保之前的线程已停止 |
|
|
|
stopCaptureThread() |
|
|
|
|
|
|
|
// 开始录音 |
|
|
|
audioRecord?.startRecording() |
|
|
|
|
|
|
|
captureThread = Thread({ |
|
|
|
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO) |
|
|
|
|
|
|
|
val supportedSampleRates = intArrayOf(16000, 8000, 11025, 22050, 44100) |
|
|
|
var bufferSize = 0 |
|
|
|
val sampleRate = supportedSampleRates.firstOrNull { rate -> |
|
|
|
bufferSize = AudioRecord.getMinBufferSize( |
|
|
|
rate, |
|
|
|
AudioFormat.CHANNEL_IN_MONO, |
|
|
|
AudioFormat.ENCODING_PCM_16BIT |
|
|
|
) |
|
|
|
bufferSize > 0 |
|
|
|
} ?: 16000 |
|
|
|
|
|
|
|
val buffer = ByteArray(bufferSize) |
|
|
|
|
|
|
|
try { |
|
|
|
while (!Thread.currentThread().isInterrupted && |
|
|
|
audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) { |
|
|
|
|
|
|
|
// 写入Azure流 |
|
|
|
pushAudioStream?.write(buffer) |
|
|
|
|
|
|
|
// 保存录音 |
|
|
|
recordfile?.saveAudioDataToWav(buffer) |
|
|
|
if (!isPaused) { |
|
|
|
val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0 |
|
|
|
if (bytesRead > 0) { |
|
|
|
// 安全地写入Azure流 |
|
|
|
try { |
|
|
|
pushAudioStream?.write(buffer) |
|
|
|
recordfile?.saveAudioDataToWav(buffer) |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.w(tag, "写入音频流失败: ${e.message}") |
|
|
|
} |
|
|
|
} else if (bytesRead < 0) { |
|
|
|
Log.w(tag, "AudioRecord读取错误: $bytesRead") |
|
|
|
break |
|
|
|
} |
|
|
|
} else { |
|
|
|
Thread.sleep(10) // 暂停时短暂休眠 |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e: InterruptedException) { |
|
|
|
Log.d(tag, "音频捕获线程被中断") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(tag, "音频捕获异常: ${e.message}", e) |
|
|
|
} |
|
|
|
}, "AudioCaptureThread") |
|
|
|
|
|
|
|
captureThread?.start() |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(tag, "启动音频捕获线程失败: ${e.message}", e) |
|
|
|
throw e |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private fun stopCaptureThread() { |
|
|
|
captureThread?.let { thread -> |
|
|
|
if (thread.isAlive) { |
|
|
|
thread.interrupt() |
|
|
|
try { |
|
|
|
thread.join(500) // 等待最多500ms |
|
|
|
} catch (e: InterruptedException) { |
|
|
|
Log.w(tag, "等待音频线程结束被中断") |
|
|
|
} |
|
|
|
} |
|
|
|
}.apply { start() } |
|
|
|
} |
|
|
|
captureThread = null |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -1050,4 +1088,4 @@ class AzureAsrHelper(private val context: Context) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |