Reputation: 1283
I'm not strictly looking for an implementation of this idea but if someone has already made it, that would be awesome and I'd like to see it. Otherwise:
I'm trying to implement a couple SeekBars
in my Android's waveform generator app. I have a couple controls such as: volume, frequency, low pass filter cutoff frequency, resonance, pitch bend, etc.
The problem with my SeekBars
are that they sound too step-y and I want it to sound more analog-ish (smoother if you will). In my iOS implementation of the app, the native UISliders
did a good job and I didn't hear any step-like movements. However, the SeekBars
aren't very smooth and tend to jump value to value (lets say like from 10 to 100 with a max value of 1000).
I was wondering if it might be best if I just design my own custom UI for a smoother slider or if there is one already. Also, is it possible that my audio thread is interrupting the SeekBar
's functionality and causing these jumps/step-like behavior?
Things I've tried already:
Lowpass the seekbar progress in the listener's onProgressChanged
. This doesn't really work (if it jumped from 5 to 100 for example, this would give me a value in between but that still doesn't give a full smooth-like behavior).
// b = 0.99, a = 0.01
// Follows simple lowpass: yn = (xn * b) + (yn1 * a)
public double lowpass(int xn) {
double yn = (xn * b) + (lastProgress * a);
lastProgress = yn;
return yn;
}
If there is a huge jump (like 5 to 100), I would call a while loop to increment the audio context's variables by 1. The problem with this is if I was trying to do a pitch bend (a 14bit number so that's 16384 values total), it would take too long to get to the target value (the pitch bend does sound cool though). for example (obviously this only accounts for progress going up):
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int myProgress = seekBar.getProgress();
while (myProgress < progress) {
// This will increase the audio context's frequency variable by one every loop until we've reached our target progress
audioContext.setFrequency(myProgress++);
}
}
Thanks!
Upvotes: 2
Views: 1155
Reputation: 666
First, figure out what is the fastest you want the volume to increase. For this example, I'll use 1 second (1000ms) to change from 0 to 1.0. (0% to 100%)
When you enter the loop, record the current time. Then, for each iteration of your loop, check the time passed and increment the necessary amount.
// example, myLoop(0.25, 0.75, startTime);
double myLoop(double start, double end, long startTime) {
long now = System.currentTimeMillis(); // (100ms since startTime)
double span = end - start; // the span in value, 0 to 1.0 (=0.5)
double timeSpan = (now - startTime) / (span * 1000); // time since started / total time of change (100/500 = 0.2)
return timeSpan * span + start; // (0.2 * 0.5 = 0.1) + 0.25 = 0.35, the value for this loop
}
(untested code)
Upvotes: 2