or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analytics.mdaudio-rendering.mdcore-player.mddrm-support.mdindex.mdmedia-sources.mdoffline-support.mdtrack-selection.mdvideo-rendering.md

audio-rendering.mddocs/

0

# Audio Rendering

1

2

Audio rendering in ExoPlayer handles decoding and outputting audio data to the Android audio system. The audio pipeline includes decoders, processors, and sinks that work together to provide high-quality audio playback with support for various codecs and audio effects.

3

4

## AudioSink Interface

5

6

The AudioSink interface defines how audio data is consumed and output to audio hardware.

7

8

```java { .api }

9

public interface AudioSink {

10

/**

11

* Exception thrown when audio sink configuration fails.

12

*/

13

final class ConfigurationException extends Exception {

14

public final Format format;

15

16

public ConfigurationException(String message, Format format);

17

public ConfigurationException(Throwable cause, Format format);

18

public ConfigurationException(String message, Throwable cause, Format format);

19

}

20

21

/**

22

* Exception thrown when audio sink write operations fail.

23

*/

24

final class WriteException extends Exception {

25

public final int errorCode;

26

public final Format format;

27

28

public WriteException(int errorCode, Format format, Throwable cause);

29

}

30

31

/**

32

* Configures the sink for the specified audio format.

33

*

34

* @param format The audio format

35

* @param specifiedBufferSize The buffer size in bytes, or 0 for default

36

* @param outputChannels The output channel configuration, or null for default

37

* @throws ConfigurationException If configuration fails

38

*/

39

void configure(Format format, int specifiedBufferSize, @Nullable int[] outputChannels) throws ConfigurationException;

40

41

/**

42

* Starts or resumes audio output.

43

*/

44

void play();

45

46

/**

47

* Pauses audio output.

48

*/

49

void pause();

50

51

/**

52

* Plays to the end of the stream.

53

*

54

* @throws WriteException If writing fails

55

*/

56

void playToEndOfStream() throws WriteException;

57

58

/**

59

* Resets the sink.

60

*/

61

void reset();

62

63

/**

64

* Releases the sink.

65

*/

66

void release();

67

68

/**

69

* Sets the audio volume.

70

*

71

* @param volume The volume (0.0 to 1.0)

72

*/

73

void setVolume(float volume);

74

75

/**

76

* Sets the audio attributes.

77

*

78

* @param audioAttributes The audio attributes

79

*/

80

void setAudioAttributes(AudioAttributes audioAttributes);

81

82

/**

83

* Sets auxiliary effect information.

84

*

85

* @param auxEffectInfo The auxiliary effect info

86

*/

87

void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);

88

89

/**

90

* Returns the current playback parameters.

91

*

92

* @return The current playback parameters

93

*/

94

PlaybackParameters getPlaybackParameters();

95

96

/**

97

* Sets playback parameters for speed and pitch adjustment.

98

*

99

* @param playbackParameters The playback parameters

100

*/

101

void setPlaybackParameters(PlaybackParameters playbackParameters);

102

103

/**

104

* Attempts to write audio data to the sink.

105

*

106

* @param buffer The audio data buffer

107

* @param presentationTimeUs The presentation time in microseconds

108

* @param encodedAccessUnitCount The number of encoded access units

109

* @return Whether the buffer was consumed

110

* @throws WriteException If writing fails

111

*/

112

boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAccessUnitCount) throws WriteException;

113

114

/**

115

* Returns the buffer size for the AudioTrack in microseconds.

116

*

117

* @return The buffer size in microseconds

118

*/

119

long getAudioTrackBufferSizeUs();

120

}

121

```

122

123

## DefaultAudioSink

124

125

The default implementation of AudioSink using Android's AudioTrack.

126

127

```java { .api }

128

public final class DefaultAudioSink implements AudioSink {

129

/**

130

* Builder for DefaultAudioSink.

131

*/

132

public static final class Builder {

133

/**

134

* Creates a builder.

135

*/

136

public Builder();

137

138

/**

139

* Sets the audio capabilities.

140

*

141

* @param audioCapabilities The audio capabilities

142

* @return This builder

143

*/

144

public Builder setAudioCapabilities(AudioCapabilities audioCapabilities);

145

146

/**

147

* Sets the audio processors.

148

*

149

* @param audioProcessors The audio processors

150

* @return This builder

151

*/

152

public Builder setAudioProcessors(AudioProcessor[] audioProcessors);

153

154

/**

155

* Sets whether to enable float output.

156

*

157

* @param enableFloatOutput Whether to enable float output

158

* @return This builder

159

*/

160

public Builder setEnableFloatOutput(boolean enableFloatOutput);

161

162

/**

163

* Sets whether to enable AudioTrack playback parameters.

164

*

165

* @param enableAudioTrackPlaybackParams Whether to enable AudioTrack playback parameters

166

* @return This builder

167

*/

168

public Builder setEnableAudioTrackPlaybackParams(boolean enableAudioTrackPlaybackParams);

169

170

/**

171

* Sets the offload mode.

172

*

173

* @param offloadMode The offload mode

174

* @return This builder

175

*/

176

public Builder setOffloadMode(@OffloadMode int offloadMode);

177

178

/**

179

* Builds the DefaultAudioSink.

180

*

181

* @return The built DefaultAudioSink

182

*/

183

public DefaultAudioSink build();

184

}

185

186

// Offload modes

187

public static final int OFFLOAD_MODE_DISABLED = 0;

188

public static final int OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED = 1;

189

public static final int OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED = 2;

190

public static final int OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED = 3;

191

}

192

```

193

194

## MediaCodecAudioRenderer

195

196

Audio renderer that uses MediaCodec for decoding.

197

198

```java { .api }

199

public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock {

200

/**

201

* Creates a MediaCodecAudioRenderer.

202

*

203

* @param context The context

204

* @param mediaCodecSelector The MediaCodec selector

205

* @param enableDecoderFallback Whether to enable decoder fallback

206

* @param eventHandler The event handler

207

* @param eventListener The event listener

208

* @param audioSink The audio sink

209

*/

210

public MediaCodecAudioRenderer(Context context, MediaCodecSelector mediaCodecSelector,

211

boolean enableDecoderFallback, @Nullable Handler eventHandler,

212

@Nullable AudioRendererEventListener eventListener, AudioSink audioSink);

213

214

/**

215

* Sets the volume.

216

*

217

* @param volume The volume (0.0 to 1.0)

218

*/

219

public final void setVolume(float volume);

220

221

/**

222

* Returns the current playback parameters.

223

*

224

* @return The current playback parameters

225

*/

226

public PlaybackParameters getPlaybackParameters();

227

228

/**

229

* Sets playback parameters.

230

*

231

* @param playbackParameters The playback parameters

232

*/

233

public void setPlaybackParameters(PlaybackParameters playbackParameters);

234

235

/**

236

* Returns the position according to the media clock.

237

*

238

* @return The position in microseconds

239

*/

240

@Override

241

public long getPositionUs();

242

243

/**

244

* Sets the audio session ID.

245

*

246

* @param audioSessionId The audio session ID

247

*/

248

public void setAudioSessionId(int audioSessionId);

249

250

/**

251

* Sets auxiliary effect information.

252

*

253

* @param auxEffectInfo The auxiliary effect info

254

*/

255

public void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);

256

}

257

```

258

259

## AudioRendererEventListener

260

261

Listener for audio renderer events.

262

263

```java { .api }

264

public interface AudioRendererEventListener {

265

/**

266

* Called when the audio renderer is enabled.

267

*

268

* @param counters The decoder counters

269

*/

270

default void onAudioEnabled(DecoderCounters counters) {}

271

272

/**

273

* Called when the audio session ID changes.

274

*

275

* @param audioSessionId The new audio session ID

276

*/

277

default void onAudioSessionIdChanged(int audioSessionId) {}

278

279

/**

280

* Called when the audio decoder is initialized.

281

*

282

* @param decoderName The decoder name

283

* @param initializedTimestampMs The initialization timestamp

284

* @param initializationDurationMs The initialization duration

285

*/

286

default void onAudioDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {}

287

288

/**

289

* Called when the audio input format changes.

290

*

291

* @param format The new format

292

* @param decoderReuseEvaluation The decoder reuse evaluation

293

*/

294

default void onAudioInputFormatChanged(Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {}

295

296

/**

297

* Called when the audio position is advancing.

298

*

299

* @param playoutStartSystemTimeMs The playout start system time

300

*/

301

default void onAudioPositionAdvancing(long playoutStartSystemTimeMs) {}

302

303

/**

304

* Called when audio underrun occurs.

305

*

306

* @param bufferSize The buffer size

307

* @param bufferSizeMs The buffer size in milliseconds

308

* @param elapsedSinceLastFeedMs Time elapsed since last feed

309

*/

310

default void onAudioUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {}

311

312

/**

313

* Called when the audio decoder is released.

314

*

315

* @param decoderName The decoder name

316

*/

317

default void onAudioDecoderReleased(String decoderName) {}

318

319

/**

320

* Called when the audio renderer is disabled.

321

*

322

* @param counters The decoder counters

323

*/

324

default void onAudioDisabled(DecoderCounters counters) {}

325

326

/**

327

* Called when the audio sink underruns.

328

*

329

* @param bufferSize The buffer size

330

* @param bufferSizeMs The buffer size in milliseconds

331

* @param elapsedSinceLastFeedMs Time elapsed since last feed

332

*/

333

default void onAudioSinkUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {}

334

335

/**

336

* Called when audio codec error occurs.

337

*

338

* @param audioCodecError The audio codec error

339

*/

340

default void onAudioCodecError(Exception audioCodecError) {}

341

}

342

```

343

344

## AudioProcessor Interface

345

346

Interface for audio processing components that can modify audio data.

347

348

```java { .api }

349

public interface AudioProcessor {

350

/**

351

* Data structure for audio format.

352

*/

353

final class AudioFormat {

354

public static final AudioFormat NOT_SET = new AudioFormat(Format.NO_VALUE, Format.NO_VALUE, Format.NO_VALUE);

355

356

public final int sampleRate;

357

public final int channelCount;

358

@C.PcmEncoding public final int encoding;

359

360

public AudioFormat(int sampleRate, int channelCount, @C.PcmEncoding int encoding);

361

}

362

363

/**

364

* Exception thrown when audio processing fails.

365

*/

366

final class UnhandledAudioFormatException extends Exception {

367

public final AudioFormat inputAudioFormat;

368

public final AudioFormat outputAudioFormat;

369

370

public UnhandledAudioFormatException(AudioFormat inputAudioFormat, AudioFormat outputAudioFormat);

371

}

372

373

/**

374

* Configures the processor for the specified input format.

375

*

376

* @param inputAudioFormat The input audio format

377

* @return The output audio format

378

* @throws UnhandledAudioFormatException If the format is not supported

379

*/

380

AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudioFormatException;

381

382

/**

383

* Returns whether the processor is active.

384

*

385

* @return Whether the processor is active

386

*/

387

boolean isActive();

388

389

/**

390

* Queues input data for processing.

391

*

392

* @param inputBuffer The input buffer

393

*/

394

void queueInput(ByteBuffer inputBuffer);

395

396

/**

397

* Queues end of stream.

398

*/

399

void queueEndOfStream();

400

401

/**

402

* Returns a buffer containing processed output data.

403

*

404

* @return The output buffer, or EMPTY_BUFFER if no output is available

405

*/

406

ByteBuffer getOutput();

407

408

/**

409

* Returns whether the processor has ended.

410

*

411

* @return Whether the processor has ended

412

*/

413

boolean isEnded();

414

415

/**

416

* Flushes the processor.

417

*/

418

void flush();

419

420

/**

421

* Resets the processor.

422

*/

423

void reset();

424

}

425

```

426

427

## Usage Examples

428

429

### Basic Audio Renderer Setup

430

431

```java

432

// Create default audio sink

433

DefaultAudioSink audioSink = new DefaultAudioSink.Builder().build();

434

435

// Create audio renderer

436

MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer(

437

context,

438

MediaCodecSelector.DEFAULT,

439

/* enableDecoderFallback= */ false,

440

/* eventHandler= */ null,

441

/* eventListener= */ null,

442

audioSink

443

);

444

445

// Use with custom renderers factory

446

RenderersFactory renderersFactory = new DefaultRenderersFactory(context) {

447

@Override

448

protected void buildAudioRenderers(Context context, int extensionRendererMode,

449

MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback,

450

AudioSink audioSink, Handler eventHandler,

451

AudioRendererEventListener eventListener,

452

ArrayList<Renderer> out) {

453

out.add(new MediaCodecAudioRenderer(context, mediaCodecSelector, enableDecoderFallback,

454

eventHandler, eventListener, audioSink));

455

}

456

};

457

```

458

459

### Audio Sink Configuration

460

461

```java

462

// Configure audio sink with custom settings

463

DefaultAudioSink audioSink = new DefaultAudioSink.Builder()

464

.setEnableFloatOutput(true) // Enable high-resolution audio

465

.setEnableAudioTrackPlaybackParams(true) // Enable speed/pitch adjustment

466

.setOffloadMode(DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED) // Enable offload

467

.build();

468

```

469

470

### Audio Event Handling

471

472

```java

473

AudioRendererEventListener audioListener = new AudioRendererEventListener() {

474

@Override

475

public void onAudioEnabled(DecoderCounters counters) {

476

Log.d(TAG, "Audio enabled");

477

}

478

479

@Override

480

public void onAudioSessionIdChanged(int audioSessionId) {

481

Log.d(TAG, "Audio session ID changed: " + audioSessionId);

482

// Apply audio effects to this session

483

applyAudioEffects(audioSessionId);

484

}

485

486

@Override

487

public void onAudioDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {

488

Log.d(TAG, "Audio decoder initialized: " + decoderName);

489

}

490

491

@Override

492

public void onAudioUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {

493

Log.w(TAG, "Audio underrun detected");

494

}

495

496

@Override

497

public void onAudioCodecError(Exception audioCodecError) {

498

Log.e(TAG, "Audio codec error", audioCodecError);

499

}

500

};

501

502

// Use with renderer

503

MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer(

504

context, MediaCodecSelector.DEFAULT, false,

505

handler, audioListener, audioSink

506

);

507

```

508

509

### Volume and Playback Control

510

511

```java

512

// Set volume on audio renderer

513

audioRenderer.setVolume(0.5f); // 50% volume

514

515

// Set playback parameters for speed/pitch adjustment

516

PlaybackParameters params = new PlaybackParameters(1.5f, 1.0f); // 1.5x speed, normal pitch

517

audioRenderer.setPlaybackParameters(params);

518

519

// Get current playback parameters

520

PlaybackParameters currentParams = audioRenderer.getPlaybackParameters();

521

```

522

523

### Audio Effects Integration

524

525

```java

526

// Apply audio effects using session ID

527

private void applyAudioEffects(int audioSessionId) {

528

// Create equalizer

529

Equalizer equalizer = new Equalizer(0, audioSessionId);

530

equalizer.setEnabled(true);

531

532

// Create bass boost

533

BassBoost bassBoost = new BassBoost(0, audioSessionId);

534

bassBoost.setStrength((short) 1000); // Maximum bass boost

535

bassBoost.setEnabled(true);

536

537

// Create virtualizer

538

Virtualizer virtualizer = new Virtualizer(0, audioSessionId);

539

virtualizer.setStrength((short) 1000); // Maximum virtualization

540

virtualizer.setEnabled(true);

541

}

542

```

543

544

### Custom Audio Processor

545

546

```java

547

public class VolumeAudioProcessor implements AudioProcessor {

548

private float volume = 1.0f;

549

private AudioFormat outputFormat;

550

private ByteBuffer buffer = EMPTY_BUFFER;

551

private boolean ended;

552

553

public void setVolume(float volume) {

554

this.volume = volume;

555

}

556

557

@Override

558

public AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudioFormatException {

559

if (inputAudioFormat.encoding != C.ENCODING_PCM_16BIT) {

560

throw new UnhandledAudioFormatException(inputAudioFormat, AudioFormat.NOT_SET);

561

}

562

this.outputFormat = inputAudioFormat;

563

return outputFormat;

564

}

565

566

@Override

567

public boolean isActive() {

568

return volume != 1.0f;

569

}

570

571

@Override

572

public void queueInput(ByteBuffer inputBuffer) {

573

if (!isActive()) {

574

buffer = inputBuffer;

575

return;

576

}

577

578

// Apply volume adjustment

579

ByteBuffer processedBuffer = ByteBuffer.allocate(inputBuffer.remaining());

580

while (inputBuffer.hasRemaining()) {

581

short sample = inputBuffer.getShort();

582

short adjustedSample = (short) (sample * volume);

583

processedBuffer.putShort(adjustedSample);

584

}

585

processedBuffer.flip();

586

buffer = processedBuffer;

587

}

588

589

@Override

590

public void queueEndOfStream() {

591

ended = true;

592

}

593

594

@Override

595

public ByteBuffer getOutput() {

596

ByteBuffer outputBuffer = buffer;

597

buffer = EMPTY_BUFFER;

598

return outputBuffer;

599

}

600

601

@Override

602

public boolean isEnded() {

603

return ended && buffer == EMPTY_BUFFER;

604

}

605

606

@Override

607

public void flush() {

608

buffer = EMPTY_BUFFER;

609

ended = false;

610

}

611

612

@Override

613

public void reset() {

614

flush();

615

outputFormat = null;

616

}

617

}

618

```