Android:MediaPlayer setVolume 函数

Posted

技术标签:

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

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

谢谢

【问题讨论】:

【参考方案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 多个小时足以在一天内花在这样的问题上)

编辑

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

    只需向 SetVolume 方法提交所需的响度。 在发送之前(基本上)对期望的响度求幂,使其成为 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);
            
        );
    

【讨论】:

以上是关于Android:MediaPlayer setVolume 函数的主要内容,如果未能解决你的问题,请参考以下文章

Android:MediaPlayer.setDataSource(FileDescriptor fd) vs MediaPlayer.setDataSource(FileDescriptor fd,

android的MediaPlayer.create方法怎么用

Android开发---MediaPlayer简单音乐播放器

Android MediaPlayer错误码整理

Android:MediaPlayer 未发布就完成了

Android -- MediaPlayer内部实现简析