@@ -19,7 +19,6 @@ package com.google.firebase.ai.type
1919import android.Manifest
2020import android.media.AudioAttributes
2121import android.media.AudioFormat
22- import android.media.AudioManager
2322import android.media.AudioRecord
2423import android.media.AudioTrack
2524import android.media.MediaRecorder
@@ -157,28 +156,39 @@ internal class AudioHelper(
157156 *
158157 * It also makes it easier to read, since the long initialization is separate from the
159158 * constructor.
159+ *
160+ * @param audioHandler A callback that is invoked immediately following the successful
161+ * initialization of the associated [AudioRecord] and [AudioTrack] objects. This offers a final
162+ * opportunity to configure these objects, which will remain valid and effective for the
163+ * duration of the current audio session.
160164 */
161165 @RequiresPermission(Manifest .permission.RECORD_AUDIO )
162- fun build (audioHandler : ((AudioRecord , AudioTrack ) -> Unit )? = null): AudioHelper {
163- val playbackTrack =
164- AudioTrack (
165- AudioAttributes .Builder ()
166- .setUsage(AudioAttributes .USAGE_MEDIA )
167- .setContentType(AudioAttributes .CONTENT_TYPE_SPEECH )
168- .build(),
166+ fun build (
167+ audioHandler : ((AudioRecord .Builder , AudioTrack .Builder ) -> Unit )? = null
168+ ): AudioHelper {
169+ val playTrackBuilder = AudioTrack .Builder ()
170+ playTrackBuilder
171+ .setAudioFormat(
169172 AudioFormat .Builder ()
170173 .setSampleRate(24000 )
171174 .setChannelMask(AudioFormat .CHANNEL_OUT_MONO )
172175 .setEncoding(AudioFormat .ENCODING_PCM_16BIT )
173- .build(),
176+ .build()
177+ )
178+ .setAudioAttributes(
179+ AudioAttributes .Builder ()
180+ .setUsage(AudioAttributes .USAGE_MEDIA )
181+ .setContentType(AudioAttributes .CONTENT_TYPE_SPEECH )
182+ .build()
183+ )
184+ .setBufferSizeInBytes(
174185 AudioTrack .getMinBufferSize(
175186 24000 ,
176187 AudioFormat .CHANNEL_OUT_MONO ,
177188 AudioFormat .ENCODING_PCM_16BIT
178189 ),
179- AudioTrack .MODE_STREAM ,
180- AudioManager .AUDIO_SESSION_ID_GENERATE
181190 )
191+ .setTransferMode(AudioTrack .MODE_STREAM )
182192
183193 val bufferSize =
184194 AudioRecord .getMinBufferSize(
@@ -191,15 +201,22 @@ internal class AudioHelper(
191201 throw AudioRecordInitializationFailedException (
192202 " Audio Record buffer size is invalid ($bufferSize )"
193203 )
194-
195- val recorder =
196- AudioRecord (
197- MediaRecorder .AudioSource .VOICE_COMMUNICATION ,
198- 16000 ,
199- AudioFormat .CHANNEL_IN_MONO ,
200- AudioFormat .ENCODING_PCM_16BIT ,
201- bufferSize
202- )
204+ val recorderBuilder =
205+ AudioRecord .Builder ()
206+ .setAudioSource(MediaRecorder .AudioSource .VOICE_COMMUNICATION )
207+ .setAudioFormat(
208+ AudioFormat .Builder ()
209+ .setEncoding(AudioFormat .ENCODING_PCM_16BIT )
210+ .setSampleRate(16000 )
211+ .setChannelMask(AudioFormat .CHANNEL_IN_MONO )
212+ .build()
213+ )
214+ .setBufferSizeInBytes(bufferSize)
215+ if (audioHandler != null ) {
216+ audioHandler(recorderBuilder, playTrackBuilder)
217+ }
218+ val recorder = recorderBuilder.build()
219+ val playbackTrack = playTrackBuilder.build()
203220 if (recorder.state != AudioRecord .STATE_INITIALIZED )
204221 throw AudioRecordInitializationFailedException (
205222 " Audio Record initialization has failed. State: ${recorder.state} "
@@ -209,9 +226,6 @@ internal class AudioHelper(
209226 AcousticEchoCanceler .create(recorder.audioSessionId)?.enabled = true
210227 }
211228
212- if (audioHandler != null ) {
213- audioHandler(recorder, playbackTrack)
214- }
215229 return AudioHelper (recorder, playbackTrack)
216230 }
217231 }
0 commit comments