VolumeShaper로 진폭 제어

오디오 앱에서 VolumeShaper를 사용하여 페이드 인, 페이드 아웃, 크로스 페이드, 볼륨 낮추기 및 기타 짧은 자동 볼륨 전환을 실행할 수 있습니다. VolumeShaper 클래스는 Android 8.0 (API 수준 26) 이상에서 사용할 수 있습니다.

AudioTrack 또는 MediaPlayer 인스턴스에서 createVolumeShaper()를 호출하여 VolumeShaper를 만듭니다. VolumeShaper는 이를 만든 AudioTrack 또는 MediaPlayer에서 생성된 오디오에만 작동합니다.

VolumeShaper.Configuration

VolumeShaper의 동작은 VolumeShaper.Configuration에 의해 정의됩니다. 이 구성은 *볼륨 곡선, 보간기 유형 지속 시간*을 지정합니다.

볼륨 곡선

볼륨 곡선은 시간에 따른 진폭 변화를 나타냅니다. 일련의 제어점을 정의하는 한 쌍의 부동 소수점 배열 x[] 및 y[] 로 정의됩니다. 각 (x, y) 쌍은 각각 시간과 볼륨을 나타냅니다. 배열은 길이가 같고 2~16개의 값을 포함해야 합니다. 최대 곡선 길이는 getMaximumCurvePoints()에서 정의됩니다.

시간 좌표는 구간 [0.0, 1.0]에서 지정됩니다. 첫 번째 시점은 0.0, 마지막 시점은 1.0이어야 하며 시간은 단조 증가해야 합니다.

볼륨 좌표는 구간 [0.0, 1.0]에서 선형 스케일로 지정됩니다.

보간기 유형

볼륨 곡선은 항상 지정된 제어점을 통과합니다. 제어점 사이의 값은 구성의 보간기 유형에 따라 스플라인에 의해 파생됩니다. 사용 가능한 VolumeShaper 보간기 유형에는 4개의 상수가 있습니다.

  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_STEP
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC
  • VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC_MONOTONIC

시간

간격 [0.0, 1.0] 에 지정된 시간 좌표는 밀리초 단위로 지정한 기간으로 조정됩니다. 이는 셰이퍼가 실행되고 오디오 출력에 곡선을 적용할 때의 실제 볼륨 곡선 길이(시간)를 결정합니다.

VolumeShaper 사용

구성 만들기

VolumeShaper를 빌드하기 전에 VolumeShaper.Configuration의 인스턴스를 생성해야 합니다. VolumeShaper.Configuration.Builder()를 사용하여 다음을 실행합니다.

Kotlin

val config: VolumeShaper.Configuration = VolumeShaper.Configuration.Builder()
        .setDuration(3000)
        .setCurve(floatArrayOf(0f, 1f), floatArrayOf(0f, 1f))
        .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
        .build()

Java

VolumeShaper.Configuration config =
  new VolumeShaper.Configuration.Builder()
      .setDuration(3000)
      .setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f})
      .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
      .build();

With no arguments the VolumeShaper.Configuration.Builder constructor returns a builder that creates a configuration with default settings: INTERPOLATOR_TYPE_CUBIC, a one second duration, and no curve. You must add a curve to the builder before calling build().

The framework provides constants for configurations with pre-built curves, each with one second duration:

  • VolumeShaper.Configuration.LINEAR_RAMP
  • VolumeShaper.Configuration.CUBIC_RAMP
  • VolumeShaper.Configuration.SINE_RAMP
  • VolumeShaper.Configuration.SCURVE_RAMP

Creating a VolumeShaper

To create a VolumeShaper, call createVolumeShaper() on an instance of the appropriate class, passing in a VolumeShaper.Configuration:

Kotlin

volumeShaper = myMediaPlayer.createVolumeShaper(config)
volumeShaper = myAudioTrack.createVolumeShaper(config)

Java

volumeShaper = myMediaPlayer.createVolumeShaper(config);
volumeShaper = myAudioTrack.createVolumeShaper(config);

A single track or media player can have many shapers attached to it, and you can control each shaper separately. The outputs of all the shapers on a track or player are multiplied together. A VolumeShaper cannot be shared between AudioTracks or MediaPlayers, but you can use the same configuration in calls to createVolumeShaper to build identical shapers on multiple AudioTracks or MediaPlayers.

When you create the shaper, its first control point (at t = 0) is applied to the audio stream. If the initial volume is not 1.0 and your app is playing material at create time, your audio might have an abrupt change in volume. Best practice is to start playing audio from silence and use a VolumeShaper to implement a fade-in when playback starts. Create a VolumeShaper that starts at 0 volume and fades up. For example:

setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f})

재생과 셰이퍼를 동시에 시작합니다. 이렇게 하면 재생이 무음에서 시작되며 볼륨이 최대 볼륨으로 올라갑니다. 이에 대해서는 다음 섹션에서 설명합니다.

VolumeShaper 실행

첫 번째 컨트롤 포인트의 볼륨 수준은 셰이퍼가 생성되는 즉시 오디오 경로에 적용되지만 셰이퍼는 VolumeShaper.Operation.PLAYapply() 메서드를 호출할 때까지 곡선을 따라 진행되지 않습니다. 셰이퍼를 만든 후 셰이퍼를 시작하려면 첫 번째 apply() 호출에서 PLAY 작업을 지정해야 합니다. 이렇게 하면 첫 번째 제어점에서 마지막 제어점까지 곡선이 실행됩니다.

Kotlin

shaper.apply(VolumeShaper.Operation.PLAY)

Java

shaper.apply(VolumeShaper.Operation.PLAY);

셰이퍼가 실행되는 동안 REVERSE 연산과 PLAY 연산을 지정하는 apply() 호출을 번갈아 실행할 수 있습니다. 이렇게 하면 매번 기준점의 판독 방향이 변경됩니다.

셰이퍼는 계속 볼륨을 조정하고 만료될 때까지 모든 컨트롤 포인트를 통과합니다. 이는 셰이퍼가 곡선의 마지막 제어점 (PLAY 작업의 경우) 또는 첫 번째 제어점 (REVERSE 연산의 경우)에 도달할 때 발생합니다.

셰이퍼가 만료되면 볼륨은 첫 번째 또는 마지막 제어점일 수 있는 마지막 설정에서 유지됩니다. 언제든지 현재 볼륨 수준에 관한 VolumeShaper.getVolume()를 호출할 수 있습니다.

셰이퍼가 만료되면 apply() 호출을 다시 실행하여 곡선을 반대 방향으로 실행할 수 있습니다. 예를 들어 PLAY를 실행하는 동안 셰이퍼가 만료된 경우 그다음 apply()REVERSE여야 합니다. PLAY가 만료된 후에 PLAY를 호출하거나 REVERSE가 만료된 후에 REVERSE를 호출하면 아무 효과가 없습니다.

PLAYREVERSE 연산을 번갈아 수행해야 합니다. 첫 번째 제어점에서 마지막 제어점까지 곡선을 재생했다가 첫 번째 제어점부터 다시 시작할 수 있는 방법은 없습니다. 다음 섹션에서 설명하는 replace() 메서드를 사용하여 곡선을 곡선 자체의 사본으로 대체할 수 있습니다. 이렇게 하면 셰이퍼가 재설정되므로 PLAY 연산을 통해 셰이퍼를 다시 시작해야 합니다.

곡선 변경

VolumeShaper의 곡선을 변경하려면 replace() 메서드를 사용합니다. 이 메서드는 구성, 연산, 조인 매개변수를 취합니다. 셰이퍼가 실행되는 동안이나 만료된 후에 언제든지 replace() 메서드를 호출할 수 있습니다.

Kotlin

val newConfig = VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(floatArrayOf(0f, 0.5f), floatArrayOf(0f, 1f))
 .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
 .build()
val,join.ShaperOperation

Java

VolumeShaper.Configuration newConfig =
 new VolumeShaper.Configuration.Builder()
 .setDuration(1000)
 .setCurve(new float[] {0.f, 0.5f}, new float[] {0.f, 1.f})
 .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_joinr.Shaper;
joinper.Shaper.sha

셰이퍼가 실행되는 동안 replace()를 호출하면 셰이퍼가 볼륨 변경을 중지하고 현재 값으로 유지됩니다. 그런 다음 셰이퍼는 첫 번째 제어점에서 새 곡선을 시작하려고 합니다. 즉, 연산 인수는 호출 후 셰이퍼의 실행 여부를 제어합니다. PLAY를 지정하면 새 곡선을 즉시 시작하고 REVERSE를 지정하면 셰이퍼가 새 곡선의 첫 번째 제어점 볼륨에서 일시중지된 상태로 유지됩니다. 나중에 apply(VolumeShaper.Operation.PLAY)를 사용하여 셰이퍼를 시작할 수 있습니다.

join = falsereplace()를 호출하면 셰이퍼는 첫 번째 제어점으로 지정된 수준에서 곡선을 시작합니다. 이는 볼륨의 불연속성을 야기할 수 있습니다. 이를 방지하려면 replace()로 설정한 상태에서 join = true를 호출하면 됩니다. 이렇게 하면 새 곡선의 첫 번째 제어점이 셰이퍼의 현재 수준으로 설정되고 첫 번째 제어점과 마지막 제어점 사이의 모든 제어점의 볼륨이 조정되어 새 곡선의 상대적 형태가 유지됩니다 (마지막 제어점은 변경되지 않음). 확장 작업은 셰이퍼의 새 곡선에서 제어점을 영구적으로 변경합니다.

VolumeShaper 제거

AudioTrack 또는 MediaPlayer가 해제되거나 더 이상 사용되지 않으면 시스템이 종료되고 가비지가 VolumeShaper를 수집합니다. 셰이퍼에서 close() 메서드를 호출하여 셰이퍼를 즉시 제거할 수 있습니다. 시스템은 약 20밀리초 이내에 오디오 파이프라인에서 셰이퍼를 삭제합니다. 오디오 재생 중에 VolumeShaper를 닫을 때는 주의해야 합니다. close()를 호출할 때 셰이퍼의 볼륨이 1.0 미만인 경우 셰이퍼의 볼륨 배율은 1.0으로 변경됩니다. 이로 인해 볼륨이 갑자기 증가할 수 있습니다.