From 131d97be807a1a3bd43c15d67ac6cef11f0b6398 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Mon, 8 May 2006 20:40:58 +0000 Subject: [PATCH] Connected volume control GUI with Controller class, and made slider non-linear. This should be reviewed, and a better algorith should be selected. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17375 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/mediaplayer/Controller.cpp | 14 ++- src/apps/mediaplayer/Controller.h | 4 + src/apps/mediaplayer/ControllerView.cpp | 4 +- .../mediaplayer/TransportControlGroup.cpp | 86 ++++++++++++++++--- src/apps/mediaplayer/TransportControlGroup.h | 6 +- 5 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp index 0149da5fbc..e5f39263ab 100644 --- a/src/apps/mediaplayer/Controller.cpp +++ b/src/apps/mediaplayer/Controller.cpp @@ -60,6 +60,7 @@ Controller::Controller() , fVideoPlayThread(-1) , fStopAudioPlayback(false) , fStopVideoPlayback(false) + , fSoundOutput(NULL) { } @@ -251,6 +252,14 @@ Controller::VolumeDown() } +void +Controller::SetVolume(float value) +{ + if (fSoundOutput) // hack... + fSoundOutput->SetVolume(value); +} + + bool Controller::IsOverlayActive() { @@ -349,8 +358,9 @@ Controller::AudioPlayThread() media_format fmt; fmt.type = B_MEDIA_RAW_AUDIO; fmt.u.raw_audio = media_multi_audio_format::wildcard; +#ifdef __HAIKU__ fmt.u.raw_audio.format = media_multi_audio_format::B_AUDIO_FLOAT; - +#endif fAudioTrack->DecodedFormat(&fmt); SoundOutput out(fName.String(), fmt.u.raw_audio); @@ -360,9 +370,11 @@ Controller::AudioPlayThread() int64 frames; media_header mh; + fSoundOutput = &out; while (!fStopAudioPlayback && B_OK == fAudioTrack->ReadFrames(buffer, &frames, &mh)) { out.Play(buffer, frames * frame_size); } + fSoundOutput = NULL; } diff --git a/src/apps/mediaplayer/Controller.h b/src/apps/mediaplayer/Controller.h index b202709325..ac069edb5e 100644 --- a/src/apps/mediaplayer/Controller.h +++ b/src/apps/mediaplayer/Controller.h @@ -27,6 +27,7 @@ class BBitmap; class BMediaFile; class BMediaTrack; +class SoundOutput; class VideoView; class Controller @@ -63,6 +64,8 @@ public: void VolumeUp(); void VolumeDown(); + + void SetVolume(float value); private: static int32 audio_play_thread(void *self); @@ -95,6 +98,7 @@ private: thread_id fVideoPlayThread; volatile bool fStopAudioPlayback; volatile bool fStopVideoPlayback; + SoundOutput * fSoundOutput; }; diff --git a/src/apps/mediaplayer/ControllerView.cpp b/src/apps/mediaplayer/ControllerView.cpp index 6efe6e4075..a8eae38628 100644 --- a/src/apps/mediaplayer/ControllerView.cpp +++ b/src/apps/mediaplayer/ControllerView.cpp @@ -135,8 +135,8 @@ ControllerView::SkipForward() void ControllerView::SetVolume(float value) { - printf("ControllerView::SetVolume(%.2f)\n", value); - // 0.0 ... 1.0 + printf("ControllerView::SetVolume(%.4f)\n", value); + fController->SetVolume(value); } diff --git a/src/apps/mediaplayer/TransportControlGroup.cpp b/src/apps/mediaplayer/TransportControlGroup.cpp index a33a4f809f..0c8898eff2 100644 --- a/src/apps/mediaplayer/TransportControlGroup.cpp +++ b/src/apps/mediaplayer/TransportControlGroup.cpp @@ -40,8 +40,15 @@ enum { #define VOLUME_MIN_WIDTH 70.0 #define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0 -#define kMaxVolume 1024 -#define kMaxSeekPos 65535 +// the range of the volume sliders (in dB) +#define kVolumeDbMax 6.0 +#define kVolumeDbMin -60.0 +// a power function for non linear sliders +#define kVolumeDbExpPositive 1.4 // for dB values > 0 +#define kVolumeDbExpNegative 1.9 // for dB values < 0 + +#define kVolumeFactor 1000 +#define kPositionFactor 65535 // constructor TransportControlGroup::TransportControlGroup(BRect frame) @@ -57,7 +64,7 @@ TransportControlGroup::TransportControlGroup(BRect frame) // Seek Slider fSeekSlider = new SeekSlider(frame, "seek slider", new BMessage(MSG_SEEK), - 0, kMaxSeekPos); + 0, kPositionFactor); fSeekSlider->ResizeToPreferred(); AddChild(fSeekSlider); @@ -142,9 +149,11 @@ TransportControlGroup::TransportControlGroup(BRect frame) // Volume Slider fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH, kVolumeSliderBitmapHeight - 1.0), - "volume slider", 0, kMaxVolume, + "volume slider", + _DbToGain(_ExponentialToLinear(kVolumeDbMin)) * kVolumeFactor, + _DbToGain(_ExponentialToLinear(kVolumeDbMax)) * kVolumeFactor, new BMessage(MSG_SET_VOLUME)); - fVolumeSlider->SetValue(128); + fVolumeSlider->SetValue(_DbToGain(_ExponentialToLinear(0.0)) * kVolumeFactor); AddChild(fVolumeSlider); } @@ -252,6 +261,59 @@ void TransportControlGroup::SetVolume(float value) {} void TransportControlGroup::ToggleMute() {} void TransportControlGroup::SetPosition(float value) {} +// #pragma mark - + + +float +TransportControlGroup::_LinearToExponential(float db_in) +{ + float db = db_in; + if (db >= 0) { + db = db * (pow(fabs(kVolumeDbMax), (1.0 / kVolumeDbExpPositive)) / fabs(kVolumeDbMax)); + db = pow(db, kVolumeDbExpPositive); + } else { + db = -db; + db = db * (pow(fabs(kVolumeDbMin), (1.0 / kVolumeDbExpNegative)) / fabs(kVolumeDbMin)); + db = pow(db, kVolumeDbExpNegative); + db = -db; + } + printf("_LinearToExponential %.4f => %.4f\n", db_in, db); + return db; +} + + +float +TransportControlGroup::_ExponentialToLinear(float db_in) +{ + float db = db_in; + if (db >= 0) { + db = pow(db, (1.0 / kVolumeDbExpPositive)); + db = db * (fabs(kVolumeDbMax) / pow(fabs(kVolumeDbMax), (1.0 / kVolumeDbExpPositive))); + } else { + db = -db; + db = pow(db, (1.0 / kVolumeDbExpNegative)); + db = db * (fabs(kVolumeDbMin) / pow(fabs(kVolumeDbMin), (1.0 / kVolumeDbExpNegative))); + db = -db; + } + printf("_ExponentialToLinear %.4f => %.4f\n", db_in, db); + return db; +} + + +float +TransportControlGroup::_DbToGain(float db) +{ + return pow(10.0, db / 20.0); +} + + +float +TransportControlGroup::_GainToDb(float gain) +{ + return 20.0 * log10(gain); +} + + // #pragma mark - // SetEnabled @@ -316,12 +378,6 @@ TransportControlGroup::SetMuted(bool mute) fVolumeSlider->SetMuted(mute); } -// Volume -uint32 -TransportControlGroup::Volume() const -{ - return fVolumeSlider->Value(); -} // #pragma mark - @@ -473,7 +529,11 @@ TransportControlGroup::_SkipForward() void TransportControlGroup::_SetVolume() { - SetVolume((float)(fVolumeSlider->Value() / 255.0)); + float pos = fVolumeSlider->Value() / (float)kVolumeFactor; + float db = _ExponentialToLinear(_GainToDb(pos)); + float gain = _DbToGain(db); + printf("_SetVolume: pos %.4f, db %.4f, gain %.4f\n", pos, db, gain); + SetVolume(gain); } // _ToggleMute @@ -488,7 +548,7 @@ TransportControlGroup::_ToggleMute() void TransportControlGroup::_UpdatePosition() { - SetPosition((float)(fSeekSlider->Value() / (float)kMaxSeekPos)); + SetPosition(fSeekSlider->Value() / (float)kPositionFactor); } diff --git a/src/apps/mediaplayer/TransportControlGroup.h b/src/apps/mediaplayer/TransportControlGroup.h index 0de8b6fcc0..ff1f3014e6 100644 --- a/src/apps/mediaplayer/TransportControlGroup.h +++ b/src/apps/mediaplayer/TransportControlGroup.h @@ -67,7 +67,6 @@ class TransportControlGroup : public BView { void SetAudioEnabled(bool enable); void SetMuted(bool mute); - uint32 Volume() const; private: void _LayoutControls(BRect frame) const; @@ -87,6 +86,11 @@ class TransportControlGroup : public BView { void _ToggleMute(); void _UpdatePosition(); + float _LinearToExponential(float db); + float _ExponentialToLinear(float db); + float _DbToGain(float db); + float _GainToDb(float gain); + SeekSlider* fSeekSlider; VolumeSlider* fVolumeSlider;