【问题标题】:Android: MediaPlayer setVolume functionAndroid:MediaPlayer setVolume 函数
【发布时间】:2011-07-10 02:00:49
【问题描述】:

关于参数 设置什么让播放器无声和全声

谢谢

【问题讨论】:

    标签: android audio media-player volume


    【解决方案1】:

    这个功能真的很棒。多亏了它,您可以创建具有任意数量步骤的音量比例!

    假设您需要 50 个步骤:

    int maxVolume = 50;
    

    然后将 setVolume 设置为此范围 (0-49) 内的任何值:

    float log1=(float)(Math.log(maxVolume-currVolume)/Math.log(maxVolume));
    yourMediaPlayer.setVolume(log1,log1); //set volume takes two paramater
    

    简单又好用!并且不要使用 AudioManager 来设置音量!它会导致很多副作用,例如禁用静音模式,这会让您的用户发疯!

    【讨论】:

    • +1000 我一直在寻找这个解决方案。极好的。谢谢!
    • 在文本转语音中尝试静音时,我必须使用 AudioManager。有没有更好的方法在 Text to Speech 中设置静音?
    • 你试过操纵 AudioManager.STREAM_MUSIC 流吗?
    • @ssuukk setVolume 方法有两个参数setVolume(float, float)。你是怎么逃过一劫的?
    • @Vadim currVolume 是 [0,maxVolume-1] 范围内的整数,因此它的值不可能是 maxVolume。请注意,对于currVolume == maxVolume-1,您会得到log1 == 0setVolume(1)(或者,使用该方法的当前签名:setVolume(1,1)),表示全音量。
    【解决方案2】:

    按照 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 之间。

    【讨论】:

    • soundVolume 是什么?它起源于哪里?
    • @SomeoneSomewhere... 它来自 SomeWhere.. :P
    • 老兄,这是我们要设置的音量...:P
    • 对于那些想知道的人来说,soundVolume 是您希望音量为 0-100 之间的变量。如果您想要更精细的调整音调,请考虑将 maxVolume 设置为 1000,然后当然将 soundVolume 保持在 0-1000 之间。
    • 请注意,即使您表示最大音量为 100。此函数实际上返回的值介于 0.0 和 1.0 之间。如果您想手动将音量重置为最大,您可以使用 mediaPlayer.setVolume(1.0, 1.0)
    【解决方案3】:

    对于Android MediaPlayer.setVolume, 搜索网络似乎显示0.0f 没有声音,1.0f 声音完整。

    【讨论】:

    • 这不是正确的解决方案。它不会线性缩放音量。我的意思是音量在 0 到 0.5 之间快速增长,但在 0.5 到 1.0 之间增长非常缓慢。查看下面的 user100858 解决方案,效果很好。
    • 1.0f 用于AudioManager 的流音量的完整声音。例如,如果流音量设置为 20%,MediaPlayer 音量设置为 1.0f,则音量将为最大音量的 20%。
    • 这个答案已经过时了。在较新版本的 Android 中,0.5 的音量是1 的 50%,这很容易。 (文档似乎确实已经过时了,但是您可以通过仔细的耳边测试/比较来确认这一点——无论如何这才是最重要的)
    【解决方案4】:

    这里的其他答案不正确——或者至少,它们没有正确配置。

    使用他们的代码(例如 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 方法所需的 Amplitude 值)

    不过,我不确定它是否正确,而且我太累了无法确认。如果有人有进一步的想法,请随时添加。 (3 多个小时足以在一天内花在这样的问题上)

    编辑

    仔细听后,比较响度-衰减效果:

    1. 只需向 SetVolume 方法提交所需的响度。
    2. 在发送之前(基本上)对期望的响度求幂,使其成为 SetVolume 方法所期望的振幅(或类似)值。

    我发现选项 1 似乎更接近于线性响度淡入!换句话说...从实际聆听和比较基本方法来看,使用此处显示的各种转换方法,似乎文档是错误的,而 SetVolume 方法实际上只是期望线性范围内的响度值。 (也许他们已经对其进行了更新,以便在最近的 API 版本之一中更直观地工作,但没有更新文档?)

    如果是这样,那肯定会很容易。这就是我现在要做的。 (虽然我会保留指数/比例固定方法作为程序设置,我想,只是为了有一个借口来保留所有投入的时间的一些结果!)

    【讨论】:

      【解决方案5】:

      正如 Venryx 所说,推荐的答案是错误的。日志数学不能那样工作(你必须减去,而不是除以日志才能让它们按你想要的方式工作)。

      不管怎样,Android 音量设置现在似乎与响度成线性比例......所以 0.5 是 1.0 的 50%,0.1 是 10%,等等。无需复杂的对数数学来将分贝转换为响度.只需按照大多数人的直觉将其设置为线性即可。

      【讨论】:

        【解决方案6】:

        我试过安卓MediaPlayer.setVolume,但是这个功能没用。

        我认为我们应该使用下面的函数

        AudioManager mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVolume * mLastProgress / 10, 0);
        

        【讨论】:

        • 是什么让MediaPlayer.setVolume 无用?你有什么不能做的?
        • AudioManager 将设置系统音量,您不想这样做。如果用户让他们的手机静音,而你突然放出音乐,他们不会欣赏它;)
        【解决方案7】:

        我在这里看到的一切都没有达到我的预期。我遇到的主要问题是,在 0 到 50 的范围内,25 从来都不是在中间,而是更接近最大声音。这里提出的日志函数对我来说几乎没有什么不同。

        要了解有关数学的更多信息,请参阅 this answer

        变量

        Linear input value   = x      // User-specified input value
        Linear scale min,max = x1,x2  // My pre-determined range of 0-50 on my UI
        Log scale min,max    = y1,y2  // Normalizes the log result to between 0-1
        Log value result     = z      // The output to pass to the setVolume() method
        

        随着价值上升变化减速的公式(最简单的形式)

        这种方法的问题是,这与我们想要的 android 的相反,因为它似乎已经默认这样做了。当您传递线性值时,当值仍然很低时,它已经增加得太快了,这进一步强调了这种效果。

        x1 + (log(x) - log(x1)) / (log(x2) - log(x1)) * (y2 - y1) = z
        

        Results of this function

        随着价值上升变化加速的公式

        这是适合我的方法;翻转输入以保持相同的变化率,但相反。有了这个,我在 25 左右获得了几乎完美的中音量,从 0 一直到 50 的听力体验非常流畅。

        y2 - (x1 + (log(x2 + x1 - x) - log(x1)) / (log(x2) - log(x1)) * (y2 - y1)) = z
        

        Results of this function

        【讨论】:

          【解决方案8】:

          此代码将音量分成 10 个相等的部分并增加或减少音量。

          Button decreaseVolButton = (Button) findViewById(R.id.decrease_volumn);
          Button increaseVolButton = (Button) findViewById(R.id.increase_volumn);
          
          final MediaPlayer mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.sample);
          
          decreaseVolButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  volume = (float) (volume - 0.1);
                  mediaPlayer.setVolume(volume, volume);
              }
          });
          increaseVolButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  volume = (float) (volume + 0.1);
                  mediaPlayer.setVolume(volume, volume);
              }
          });
          

          如果要将音量设置为无声音,则通过 (0f,0f)

          如果您想将音量设置为全音量,请通过 (1f,1f)

          【讨论】:

            【解决方案9】:

            为什么要搞得这么复杂?我正在使用这个简单的公式:

            public float getVolume() {
                float currVolume = (float) sp.getInt("volume", 10);
                float maxVolume = 15.0f;
                float result = currVolume / maxVolume;
                return result;
            }
            

            并在媒体播放器中设置此值,例如:

            player.setVolume(getVolume(), getVolume());
            

            【讨论】:

            • 上面这段代码sn-p中的sp是什么?共享首选项?
            • MediaPlayer 文档建议:“请注意,传递的音量值是 0.0 到 1.0 范围内的原始标量。UI 控件应按对数进行缩放。”。
            • FuzzyAmi ,是的 sp 是共享偏好。
            • @PawełNadolski 除以最大音量后,结果将等于或小于 1.0。
            • @Jan,是的,但它不会被对数缩放:) 所以,你的方法是正确的,但官方文档不推荐。
            【解决方案10】:

            由于体积是线性缩放的,因此不需要复杂的日志功能。调整 maxVolume,它是下面示例代码中的 100 个步骤,根据您喜欢的步骤,它应该可以工作。希望这会有所帮助。

            MediaPlayer myPlayer = MediaPlayer.create(MainActivity.this, R.raw.myAudioResource);
            
            final float maxVolume = 100.0f;
            float currentVolume = 5.0f;
            
            myPlayer.setVolume(currentVolume/maxVolume, currentVolume/maxVolume);
            myPlayer.start();
            

            【讨论】:

              【解决方案11】:

              好吧,我做了以下代码,它有点工作:

              public class MainActivity extends Activity {
              
                  float volumeLevel = 0.5f;
              
                  @Override
                  protected void onCreate(Bundle savedInstanceState) {
                      super.onCreate(savedInstanceState);
                      setContentView(R.layout.activity_main);
              
                      volumeUp = findViewById(R.id.volUp);
                      volumeDown = findViewById(R.id.volDown);
              
                      song = MediaPlayer.create(this, R.raw.audioFile);    
              
                      volumeUp.setOnClickListener(new View.OnClickListener() {
                          @Override
                          public void onClick(View v){
                              volumeLevel = volumeLevel + 0.1f;
                              song.setVolume(volumeLevel,volumeLevel);
                          }
                      });
              
                      volumeDown.setOnClickListener(new View.OnClickListener() {
                          @Override
                          public void onClick(View view) {
                              volumeLevel = volumeLevel - 0.1f;
                              song.setVolume(volumeLevel,volumeLevel);
                          }
                      });
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-01-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多