如何使播放的音乐的响度与计时器一起振荡?



我正在尝试在这个应用程序上发出第二个声音。 根据作为时间流逝的函数的 Sin 曲线在音量上振荡。您如何建议我编辑我已经拥有的内容才能完成这项工作?任何帮助都会很棒!

对不起,如果某些代码不好,我离开了一段时间,我添加了一些我之前注释掉的部分。我不确定这是否是有充分理由的,所以我把它加了回去。

MediaPlayer beep;
MediaPlayer sound2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //call superclass onCreate
setContentView(R.layout.activity_main); //inflate the GUI

minutesChanged = (TextView) findViewById(R.id.minutesChanged);
secondsChanged = (TextView) findViewById(R.id.secondsChanged);
minutesTotal = (TextView) findViewById(R.id.totalMinutesEntered);
secondsTotal = (TextView) findViewById(R.id.totalSecondsEntered);
percentageFinishedAmount = (TextView) findViewById(R.id.percentageFinishedAmount);
errorMessage = (TextView) findViewById(R.id.errorMessage);

secondEditText =
(EditText) findViewById(R.id.secondEditText);
secondEditText.addTextChangedListener(secondEditTextWatcher);

minuteEditText =
(EditText) findViewById(R.id.minuteEditText);
minuteEditText.addTextChangedListener(minuteEditTextWatcher);
whichSound =
(EditText) findViewById(R.id.whichSound);
whichSound.addTextChangedListener(whichSoundTextWatcher);
seekBarSeconds =
(SeekBar) findViewById(R.id.seekBarSeconds);
seekBarSeconds.setOnSeekBarChangeListener(seekBarListener);
seekBarMinutes =
(SeekBar) findViewById(R.id.seekBarMinutes);
seekBarMinutes.setOnSeekBarChangeListener(seekBarListener);
percentSeekBar =
(SeekBar) findViewById(R.id.seekBarTotal);
beep = MediaPlayer.create(MainActivity.this, R.raw.beep);
sound2 = MediaPlayer.create(MainActivity.this, R.raw.sound);

}
private void calculate() {
totalmili = minutesT + secondsT;

new CountDownTimer(totalmili + 2000, interv) {
public void onTick(long millisUntilFinished) {
secondsEllapsed = (int) ((totalmili + 2000 - millisUntilFinished) / 1000);
minutesEllapsed = secondsEllapsed / 60;
secondsEllapsed = secondsEllapsed % 60;

totalTimeEllapsed = secondsEllapsed + (minutesEllapsed * 60);
Log.d("Lucas", "total time elapsed " + totalTimeEllapsed);

if (totalTimeEllapsed < 10) {
errorMessage.setText("Elapsed Time: " + minutesEllapsed + " : 0" + secondsEllapsed);
} else if (totalTimeEllapsed >= 10) {
errorMessage.setText("Elapsed Time: " + minutesEllapsed + " : " + secondsEllapsed);
}
//set seekBar minutes/seconds and changing minute/seconds textView
seekBarMinutes.setProgress(minutesEllapsed);
minutesChanged.setText(Integer.toString(minutesEllapsed));
seekBarSeconds.setProgress(secondsEllapsed);
secondsChanged.setText(Integer.toString(secondsEllapsed));
double t = sin((360/totalmili) *(totalTimeEllapsed*1000));
float left = (float) ((t+1.0)*0.9/2.0+0.1);
float right = (float) ((t+1.0)*0.9/2.0+0.1);
sound2.setVolume(left,right);
Log.d("Lucas", "value of left and red respectively " + left + ", " +right);
if(sound == 1){
musicPlaying = beep.isPlaying();
if(musicPlaying == true){
beep.pause();
beep.seekTo(0);
beep.start();
} else {
beep.start();
}

}else if (sound == 2){
if(start ==1) {
sound2.seekTo(19);
sound2.start();
start = 2;

float left = (float) ((sin(totalTimeEllapsed)+1.0)*0.9/2.0+0.1);
float right = (float) ((sin(totalTimeEllapsed)+1.0)*0.9/2.0+0.1);
sound2.setVolume(left, right);
Log.d("Lucas", "value of left and red respectively " + left + ", " +right);
musicPlaying = sound2.isPlaying();
}else if(start ==2){
if (totalTimeEllapsed == 11) {
sound2.pause();
sound2.seekTo(34);
sound2.start();


} else if (totalTimeEllapsed == 22) {
sound2.pause();
}
}

//calculate total percentage finished, set percentage text, set total percentage seekBar
int percentProgress = (int) Math.round(((double) totalTimeEllapsed) / ((double) (totalmili) / 1000) * 100);
percentageFinishedAmount.setText(percentProgress + "% ");
percentSeekBar.setProgress(percentProgress);
//change background and text color bassed on increasing progress
errorMessage.setBackgroundColor(Color.argb(255, (int) (percentProgress * 2.5), 0, 0));
errorMessage.setTextColor(Color.argb(255, (int) (255 - (percentProgress * 2.5)), 255, 255));
}
public void onFinish() {
//display on finish text
errorMessage.setText("Done!");
}
}.start();

}
//listener object for the EditText's text-changed events
private final TextWatcher minuteEditTextWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// set hours Total and converts minutes to milliseconds
if (s.charAt(start + count - 1) == 'n') {
minuteEditText.getText().replace(start + count - 1, start + count, " ");
s = minuteEditText.getText();
Log.d("Lucas", "in enter key min, s = " + s);
try {
minutesT = Integer.parseInt(s.toString());
minutesTotal.setText(String.valueOf(minutesT) + " Minutes");
percentageFinishedAmount.setText(" ");
minutesT *= 60000;
} catch (NumberFormatException e) {
minutesTotal.setText("");
minutesT = 0;
}
}
}

@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(
CharSequence s, int start, int count, int after) {
}
};

// listener object for the EditText's text-changed events
private final TextWatcher secondEditTextWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
//  set minutes Total when text is changed, calls calculate, changes seconds to milliseconds
if (s.charAt(start + count - 1) == 'n') {
secondEditText.getText().replace(start + count - 1, start + count, " ");
s = secondEditText.getText();
Log.d("Lucas", "in enter key sec, s = " + s);

try {
secondsT = Integer.parseInt(s.toString());
secondsTotal.setText(String.valueOf(secondsT) + " Seconds");
secondsT *= 1000;
percentageFinishedAmount.setText(" ");
calculate();
} catch (NumberFormatException e) {
secondsTotal.setText("");
secondsT = 0;
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(
CharSequence s, int start, int count, int after) {
}
};

Yowza。我不太清楚这里的要求是什么或你在做什么。

我的方法会完全不同,也许会错过你正在尝试的重点。它将具有以下元素:

1(通过SourceDataLine输出,因为这为您提供了一个影响每帧音量的句柄。

2( 每帧,查阅指向 Sin LUT 的指针,该指针具有与所需速率相对应所需的相同数量的元素。(但是,只需将参数创建到正弦函数中也可以,该函数每帧递增正确的数量以获得所需的速率。无需就功能或LUT的性能是否更好而陷入争论。

3( 将 SDL 帧乘以 Sin LUT 值。

例如,1 Hz 的 LFO 意味着 LUT 为 44100 个元素,或者参数每帧递增 1/44100。

至于访问单个声音帧,请参阅教程使用文件和格式转换器/读取声音文件,并在示例中查找带有注释"在这里,对现在在 audioBytes 数组中的音频数据做一些有用的事情"的要点。有用的事情是将字节转换为PCM(还有其他StackOverflow解释如何(,获取下一个sin函数值并相乘,然后转换回字节。

编辑: 研究MediaPlayer API,我不清楚你是否能够有效地用这个类做你想做的事情。

玩家没有准备好准立即响应命令 直到其状态已转换为 MediaPlayer.Status.READY,这 实际上,通常在媒体预贴片完成时发生。

这是否意味着某种缓冲区大小将限制您可以进行卷更新的频率?IDK。当我们遇到缓冲区大小问题时,实际上强制执行每秒最大数量的更新,必须仔细聆听以检查当音量从一个级别跳到另一个级别时,由于不连续性而没有点击或压缩。很大程度上还取决于当您为每个音量变化设置位置时引擎盖下发生的开销量。

使用SourceDataLine输出,您可以干净地访问每个框架,这几乎消除了潜在的拉链问题。我应该添加免责声明,尽管我没有努力使用MediaPlayer,并且可能对您可以利用的功能一无所知。无论如何,SDL 级别低、功能强大且高效。

最新更新