Android: функция MediaPlayer setVolume



Answers

Следуя решению user100858, я просто разместил свой точный код, который работает:

private final static int MAX_VOLUME = 100;
...
...
final float volume = (float) (1 - (Math.log(MAX_VOLUME - soundVolume) / Math.log(MAX_VOLUME)));
mediaPlayer.setVolume(volume, volume);

soundVolume - том, который вы хотите установить, между 0 и MAX_VOLUME. Таким образом, между 0 и 100 в этом примере.

Question

о параметрах Установите, что сделать проигрывателем без звука и полного звука

благодаря




Рекомендуемый ответ неверен, как заявил Венрикс. Log math не работает таким образом (вы должны вычитать, а не делить журналы, чтобы заставить их работать так, как вы хотите).

Независимо от того, похоже, что настройка громкости Android теперь пропорциональна Loudness линейно ... так что 0,5 составляет 50% громче, чем 1,0, а 0,1 - 10% и т. Д. Нет необходимости в сложной логической математике для преобразования децибел в громкость. Просто установите его линейно, как интуитивно для большинства людей.




Другие ответы здесь неверны - или, по крайней мере, они не настроены должным образом.

Выполните следующий тест, используя свой код (например, Tomasz или ssuukk):

1) Установите 100 как «максимальный объем» / количество шагов и введите том 50.

Он возвращает: 0.150514997831991

2) Установите 1000 как «максимальный объем» / количество шагов и подайте объем 500.

Что он возвращает? То же самое значение, 0.150514997831991, правильно?

Неа. Вместо этого это: 0.100343331887994

Другими словами, существующие ответы изменяют, как они масштабируют входной объем-процент (т. Е. Кривую трансформации) в зависимости от того, сколько установленных уровней громкости .

Последние несколько часов я занимался этим вопросом; достаточно, чтобы мне не хотелось слишком подробно объяснять эту проблему. Вместо этого я просто опубликую большой блок кода / комментария в моей программе относительно этого. (он находится на C #, для Xamarin Android, но функциональность должна быть одинаковой для Java)

public enum VolumeScaleType
{
    //Energy, // what MediaPlayer possibly treats passed values as
    Amplitude, // what MediaPlayer most likely treats passed values as
    Loudness // what people treat everyday volume values as (as in "that sounded 2 times as loud")
}

// MediaPlayer
/*public static void SetVolume_IncorrectSOApproach(this MediaPlayer s, double volume, VolumeScaleType volumeType = VolumeScaleType.Loudness)
{
    const int maxVolume = 100;
    var volume_toScale = volume * maxVolume;
    double volume_scalar = volumeType == VolumeScaleType.Amplitude ? volume : (1 - (Math.Log(maxVolume - volume_toScale) / Math.Log(maxVolume)));
    s.SetVolume((float)volume_scalar, (float)volume_scalar);
}*/

public static void SetVolume_MyPossiblyCorrectApproach(this MediaPlayer s, double volume, VolumeScaleType volumeType = VolumeScaleType.Loudness)
{
    // Links:
    // 1) http://en.wikipedia.org/wiki/Decibel
    // 2) http://trace.wisc.edu/docs/2004-About-dB
    // 3) http://hyperphysics.phy-astr.gsu.edu/hbase/sound/loud.html
    // 4) http://www.animations.physics.unsw.edu.au/jw/dB.htm
    // 5) http://www.soundmaskingblog.com/2012/06/saved_by_the_bell
    // 6) http://www.campanellaacoustics.com/faq.html
    // 7) http://physics.stackexchange.com/questions/9113/how-sound-intensity-db-and-sound-pressure-level-db-are-related
    // 8) http://www.sengpielaudio.com/calculator-loudness.htm (note: page uses terms 'power/intensity' and 'pressure' differently; power/intensity: for whole shell at distance, pressure: field-quantity?)
    // basic idea: you can think of one decibel (of gain), + or -, as *translating into* the given changes-in/multipliers-for energy, amplitude, or loudness
    // (i.e. one decibel provides a specific amount to multiply energy, amplitude, and loudness values, such that they remain aligned realistically)
    // note: the 'one decibel' unit is set up to correspond roughly to a change in loudness just substantial enough to be noticeable
    // note: the 'quietest perceivable sound' example (standard) base has these absolute values: 'e' is 1 pico-watt per square-foot, 'a' is 20 micropascals, 'l' is the quietest-perceivable-loudness

    // references (for q.p.s. base)   | db (gain) | energy           | amplitude            | loudness
    // ===============================================================================================
    // actual silence                 | -inf      | 0                | 0                    | 0
    // (a seeming silence)            | -20       | e / 100          | a / 10               | 0 (would be l / 4, if 'l' weren't already for the quietest-perceivable-sound)
    // (a seeming silence)            | -10       | e / 10           | a / 3.16227/sqrt(10) | 0 (would be l / 2, if 'l' weren't already for the quietest-perceivable-sound)
    // quietest perceivable sound     | 0         | e                | a                    | l
    // ?                              | 1         | e * 1.258925     | a * 1.122018         | l * 1.071773
    // rustling leaves                | 10        | e * 10           | a * 3.16227/sqrt(10) | l * 2
    // whisper, or rural nighttime    | 20        | e * 100          | a * 10               | l * 4
    // watch ticking                  | 30        | e * 1000         | a * 31.622/sqrt(100) | l * 8
    // quiet speech, or rural daytime | 40        | e * 10000        | a * 100              | l * 16
    // dishwasher in next room        | 50        | e * 100000       | a * 316/sqrt(100000) | l * 32
    // ordinary conversation          | 60        | e * 1000000      | a * 1000             | l * 64
    // ===============================================================================================

    // assuming MediaPlayer.SetVolume treats passed values as Amplitude
    Func<double, double> convertLoudnessToAmplitude = loudness=>Math.Pow(10, Math.Log(loudness, 4));
    var volume_amplitude = volumeType == VolumeScaleType.Amplitude ? volume : convertLoudnessToAmplitude(volume);
    s.SetVolume((float)volume_amplitude, (float)volume_amplitude);
    // assuming MediaPlayer.SetVolume treats passed values as Energy
    //Func<double, double> convertLoudnessToEnergy = loudness=>Math.Pow(100, Math.Log(loudness, 4));
    //var volume_energy = volumeType == VolumeScaleType.Energy ? volume : convertLoudnessToEnergy(volume);
    //s.SetVolume((float)volume_energy, (float)volume_energy);
}

Вывод

Документация разрежена, поэтому я не могу точно знать, есть ли у меня правильная система масштабирования / тип единицы, которую ожидает метод SetVolume.

Предполагая, что он ожидает значение амплитуды, приведенный выше код может быть правильным для него. (принимая желаемую Громкость, линейную, в качестве входа и вывод / установку значения амплитуды, необходимого для встроенного метода SetVolume)

Я не уверен, что это правильно, но я слишком устал, чтобы подтвердить это. Если у кого есть дальнейшие мысли, не стесняйтесь их добавлять. (Достаточно 3 часов, чтобы потратить на такую ​​проблему, за один день)

редактировать

После тщательного прослушивания и сравнения эффекта затухания громкости:

  1. Просто передайте желаемую громкость методу SetVolume.
  2. Экспоненциальная (в основном) желаемая громкость перед отправкой в ​​нее, чтобы сделать это значение амплитуды (или тому подобное), которое, по мнению метода SetVolume, ожидает.

Я считаю, что вариант 1, кажется, ближе к линейной громкости затухает! Другими словами ... от фактического прослушивания и сравнения базового подхода, с представленными здесь различными преобразованиями, кажется, что документация неверна, и метод SetVolume действительно просто ожидает значения громкости в линейном масштабе. (возможно, они обновили его, чтобы работать более интуитивно в одной из последних версий API, но не обновили документы?)

Если это так, то это упростит. На этом я и собираюсь. (хотя я буду придерживаться подхода к возведению / масштабирования в качестве настройки программы, я полагаю, просто для того, чтобы иметь оправдание, чтобы сохранить какой-то результат за все это время!)




Links