mirror of
https://github.com/Michatec/Radio.git
synced 2026-05-31 07:02:39 +02:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d0980a1ef | |||
| ae215691ca | |||
| 52f1a57de3 | |||
| 53abe918ca |
@@ -92,18 +92,34 @@ public:
|
|||||||
*/
|
*/
|
||||||
class Reverb {
|
class Reverb {
|
||||||
public:
|
public:
|
||||||
std::vector<float> delayLine;
|
std::vector<float> d1, d2, d3;
|
||||||
int pos = 0;
|
size_t p1 = 0, p2 = 0, p3 = 0;
|
||||||
float feedback = 0.4f;
|
|
||||||
|
float feedback = 0.7f;
|
||||||
float mix = 0.0f;
|
float mix = 0.0f;
|
||||||
|
|
||||||
Reverb() { delayLine.resize(4410, 0.0f); } // ~100ms
|
Reverb() {
|
||||||
|
d1.resize(11025, 0.0f); // 250ms
|
||||||
|
d2.resize(14700, 0.0f); // 333ms
|
||||||
|
d3.resize(17640, 0.0f); // 400ms
|
||||||
|
}
|
||||||
|
|
||||||
float process(float in) {
|
float process(float in) {
|
||||||
float delayed = delayLine[static_cast<size_t>(pos)];
|
float y1 = d1[p1];
|
||||||
delayLine[static_cast<size_t>(pos)] = in + delayed * feedback;
|
float y2 = d2[p2];
|
||||||
pos = (pos + 1) % static_cast<int>(delayLine.size());
|
float y3 = d3[p3];
|
||||||
return in + delayed * mix;
|
|
||||||
|
d1[p1] = in + y1 * feedback;
|
||||||
|
d2[p2] = in + y2 * feedback;
|
||||||
|
d3[p3] = in + y3 * feedback;
|
||||||
|
|
||||||
|
p1 = (p1 + 1) % d1.size();
|
||||||
|
p2 = (p2 + 1) % d2.size();
|
||||||
|
p3 = (p3 + 1) % d3.size();
|
||||||
|
|
||||||
|
float reverb = (y1 + y2 + y3) / 3.0f;
|
||||||
|
|
||||||
|
return in * (1.0f - mix) + reverb * mix;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -189,4 +205,4 @@ Java_com_michatec_radio_helpers_NativeAudioProcessor_processAudio(JNIEnv *env, j
|
|||||||
env->ReleaseShortArrayElements(data, buffer, 0);
|
env->ReleaseShortArrayElements(data, buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
|||||||
castPlayer = CastPlayer.Builder(this).setLocalPlayer(exoPlayer).build()
|
castPlayer = CastPlayer.Builder(this).setLocalPlayer(exoPlayer).build()
|
||||||
|
|
||||||
// manually add seek to next and seek to previous since headphones issue them, and they are translated to next and previous station
|
// manually add seek to next and seek to previous since headphones issue them, and they are translated to next and previous station
|
||||||
player = object : ForwardingPlayer(exoPlayer) {
|
// IMPORTANT: Use castPlayer here instead of exoPlayer so the session controls both local and remote playback
|
||||||
|
player = object : ForwardingPlayer(castPlayer) {
|
||||||
override fun getAvailableCommands(): Player.Commands {
|
override fun getAvailableCommands(): Player.Commands {
|
||||||
return super.getAvailableCommands().buildUpon().add(COMMAND_SEEK_TO_NEXT)
|
return super.getAvailableCommands().buildUpon().add(COMMAND_SEEK_TO_NEXT)
|
||||||
.add(COMMAND_SEEK_TO_PREVIOUS).build()
|
.add(COMMAND_SEEK_TO_PREVIOUS).build()
|
||||||
@@ -170,6 +171,7 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
|||||||
return C.TIME_UNSET // this will hide progress bar for HLS stations in the notification
|
return C.TIME_UNSET // this will hide progress bar for HLS stations in the notification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
player.addListener(playerListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -483,35 +485,23 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
|||||||
isPlaying
|
isPlaying
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isPlaying) {
|
if (!isPlaying) {
|
||||||
// playback is active
|
|
||||||
} else {
|
|
||||||
// cancel sleep timer
|
// cancel sleep timer
|
||||||
cancelSleepTimer()
|
cancelSleepTimer()
|
||||||
// reset metadata
|
// reset metadata
|
||||||
updateMetadata()
|
updateMetadata()
|
||||||
|
|
||||||
// playback is not active
|
// Check playback state to decide whether to stop the service
|
||||||
// Not playing because playback is paused, ended, suppressed, or the player
|
|
||||||
// is buffering, stopped or failed. Check player.getPlayWhenReady,
|
|
||||||
// player.getPlaybackState, player.getPlaybackSuppressionReason and
|
|
||||||
// player.getPlaybackError for details.
|
|
||||||
when (player.playbackState) {
|
when (player.playbackState) {
|
||||||
// player is able to immediately play from its current position
|
Player.STATE_ENDED, Player.STATE_IDLE -> {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
Player.STATE_READY -> {
|
Player.STATE_READY -> {
|
||||||
|
// Playback is paused. For radio, we can stop the service to remove the notification.
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
// buffering - data needs to be loaded
|
|
||||||
Player.STATE_BUFFERING -> {
|
Player.STATE_BUFFERING -> {
|
||||||
stopSelf()
|
// DO NOT stop the service while buffering (especially important for Cast)
|
||||||
}
|
|
||||||
// player finished playing all media
|
|
||||||
Player.STATE_ENDED -> {
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
// initial state or player is stopped or playback failed
|
|
||||||
Player.STATE_IDLE -> {
|
|
||||||
stopSelf()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,13 +510,9 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
|||||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||||
super.onPlayWhenReadyChanged(playWhenReady, reason)
|
super.onPlayWhenReadyChanged(playWhenReady, reason)
|
||||||
if (!playWhenReady) {
|
if (!playWhenReady) {
|
||||||
when (reason) {
|
// Only stop if not buffering and not ready to play (i.e. truly stopped/paused)
|
||||||
Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM -> {
|
if (player.playbackState != Player.STATE_BUFFERING) {
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user