diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp index b94d5cc291..2a67e148fe 100644 --- a/src/apps/mediaplayer/Controller.cpp +++ b/src/apps/mediaplayer/Controller.cpp @@ -159,8 +159,10 @@ Controller::SetTo(const entry_ref &ref) BAutolock _(this); if (fRef == ref) { - SetCurrentFrame(0); - StartPlaying(); + if (InitCheck() == B_OK) { + SetCurrentFrame(0); + StartPlaying(); + } return B_OK; } @@ -233,8 +235,8 @@ Controller::SetTo(const entry_ref &ref) printf("Controller::SetTo: %d audio track, %d video track\n", AudioTrackCount(), VideoTrackCount()); - mediaFileDeleter.Detach(); fMediaFile = mf; + mediaFileDeleter.Detach(); SelectAudioTrack(0); SelectVideoTrack(0); @@ -269,13 +271,12 @@ Controller::SetTo(const entry_ref &ref) preferredVideoFormat); } - SetCurrentFrame(0); + _NotifyFileChanged(); + SetCurrentFrame(0); if (fAutoplay) StartPlaying(true); - _NotifyFileChanged(); - return B_OK; } @@ -477,9 +478,7 @@ Controller::SetVolume(float value) ToggleMute(); fVolume = value; -// TODO: apply to AutioProducer node -// if (fSoundOutput) -// fSoundOutput->SetVolume(fVolume); + fAudioSupplier->SetVolume(fVolume); _NotifyVolumeChanged(fVolume); } @@ -509,13 +508,10 @@ Controller::ToggleMute() fMuted = !fMuted; -// TODO: apply to AudioProducer node -// if (fSoundOutput) { -// if (fMuted) -// fSoundOutput->SetVolume(0.0); -// else -// fSoundOutput->SetVolume(fVolume); -// } + if (fMuted) + fAudioSupplier->SetVolume(0.0); + else + fAudioSupplier->SetVolume(fVolume); _NotifyMutedChanged(fMuted); diff --git a/src/apps/mediaplayer/Jamfile b/src/apps/mediaplayer/Jamfile index e0a7003e20..3dae93bf66 100644 --- a/src/apps/mediaplayer/Jamfile +++ b/src/apps/mediaplayer/Jamfile @@ -44,6 +44,7 @@ Application MediaPlayer : AudioReader.cpp AudioResampler.cpp AudioSupplier.cpp + AudioVolumeConverter.cpp # media_node_framework/video VideoConsumer.cpp diff --git a/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.cpp b/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.cpp new file mode 100644 index 0000000000..ff78c8da32 --- /dev/null +++ b/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.cpp @@ -0,0 +1,169 @@ +/* + * Copyright © 2008 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT licensce. + */ + +#include "AudioVolumeConverter.h" + +#include +#include + +#include + + +//#define TRACE_AUDIO_CONVERTER +#ifdef TRACE_AUDIO_CONVERTER +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) +#endif + + +AudioVolumeConverter::AudioVolumeConverter(AudioReader* source, float volume) + : AudioReader(), + fSource(NULL), + fVolume(volume), + fPreviousVolume(volume) +{ + if (source && source->Format().type == B_MEDIA_RAW_AUDIO) + fFormat = source->Format(); + else + source = NULL; + fSource = source; +} + + +AudioVolumeConverter::~AudioVolumeConverter() +{ +} + + +template +static void +convert(SampleType* buffer, const int32 samples, const float volume, + const float rounding) +{ + for (int32 i = 0; i < samples; i++) { + *buffer = (SampleType)(*buffer * volume + rounding); + buffer++; + } +} + + +template +static void +convert(SampleType* buffer, const int32 frames, const int32 channels, + const float volume1, const float volume2, const float rounding) +{ + float volumeDiff = volume2 - volume1; + for (int32 i = 0; i < frames; i++) { + float volume = volume1 + volumeDiff * (i / (frames - 1)); + for (int32 k = 0; k < channels; k++) { + *buffer = (SampleType)(*buffer * volume + rounding); + buffer++; + } + } +} + + +status_t +AudioVolumeConverter::Read(void* buffer, int64 pos, int64 frames) +{ + TRACE("AudioVolumeConverter::Read(%p, %lld, %lld)\n", buffer, pos, frames); + status_t error = InitCheck(); + if (error != B_OK) { + TRACE("AudioVolumeConverter::Read() done 1\n"); + return error; + } + pos += fOutOffset; + + status_t ret = fSource->Read(buffer, pos, frames); + if (fPreviousVolume == 1.0 && fVolume == 1.0) { + TRACE("AudioVolumeConverter::Read() done 2\n"); + return ret; + } + + int32 channelCount = fFormat.u.raw_audio.channel_count; + int32 samples = frames * channelCount; + + // apply volume + switch (fSource->Format().u.raw_audio.format) { + case media_raw_audio_format::B_AUDIO_FLOAT: + if (fVolume != fPreviousVolume) { + convert((float*)buffer, frames, channelCount, + fPreviousVolume, fVolume, 0.0); + } else + convert((float*)buffer, samples, fVolume, 0.0); + break; + case media_raw_audio_format::B_AUDIO_INT: + if (fVolume != fPreviousVolume) { + convert((int32*)buffer, frames, channelCount, + fPreviousVolume, fVolume, 0.5); + } else + convert((int32*)buffer, samples, fVolume, 0.5); + break; + case media_raw_audio_format::B_AUDIO_SHORT: + if (fVolume != fPreviousVolume) { + convert((int16*)buffer, frames, channelCount, + fPreviousVolume, fVolume, 0.5); + } else + convert((int16*)buffer, samples, fVolume, 0.5); + break; + case media_raw_audio_format::B_AUDIO_UCHAR: { + // handle this extra, because center != 0 + // (also ignores ramping the volume) + uchar* b = (uchar*)buffer; + for (int32 i = 0; i < samples; i++) { + *b = (uchar)(((float)*b - 128) * fVolume + 128.5); + b++; + } + break; + } + case media_raw_audio_format::B_AUDIO_CHAR: + if (fVolume != fPreviousVolume) { + convert((int8*)buffer, frames, channelCount, + fPreviousVolume, fVolume, 0.0); + } else + convert((int8*)buffer, samples, fVolume, 0.5); + break; + } + + fPreviousVolume = fVolume; + + TRACE("AudioVolumeConverter::Read() done\n"); + return B_OK; +} + + +status_t +AudioVolumeConverter::InitCheck() const +{ + status_t error = AudioReader::InitCheck(); + if (error == B_OK && !fSource) + error = B_NO_INIT; + if (error == B_OK) + error = fSource->InitCheck(); + return error; +} + + +AudioReader* +AudioVolumeConverter::Source() const +{ + return fSource; +} + + +void +AudioVolumeConverter::SetVolume(float volume) +{ + fVolume = volume; +} + + +float +AudioVolumeConverter::Volume() const +{ + return fVolume; +} + diff --git a/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.h b/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.h new file mode 100644 index 0000000000..a3293e1126 --- /dev/null +++ b/src/apps/mediaplayer/media_node_framework/audio/AudioVolumeConverter.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2008 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT licensce. + */ + +/*! This AudioReader just filters the volume. It depends on floating point + * audio format. +*/ + +#ifndef AUDIO_VOLUME_CONVERTER_H +#define AUDIO_VOLUME_CONVERTER_H + +#include "AudioReader.h" + +class AudioVolumeConverter : public AudioReader { +public: + AudioVolumeConverter(AudioReader* source, + float volume = 1.0); + virtual ~AudioVolumeConverter(); + + virtual status_t Read(void* buffer, int64 pos, int64 frames); + + virtual status_t InitCheck() const; + + AudioReader* Source() const; + + void SetVolume(float volume); + float Volume() const; + +protected: + AudioReader* fSource; + float fVolume; + float fPreviousVolume; +}; + +#endif // AUDIO_VOLUME_CONVERTER_H diff --git a/src/apps/mediaplayer/supplier/ProxyAudioSupplier.cpp b/src/apps/mediaplayer/supplier/ProxyAudioSupplier.cpp index 7bec173997..5349bfadd8 100644 --- a/src/apps/mediaplayer/supplier/ProxyAudioSupplier.cpp +++ b/src/apps/mediaplayer/supplier/ProxyAudioSupplier.cpp @@ -14,6 +14,7 @@ #include "AudioTrackSupplier.h" #include "AudioAdapter.h" +#include "AudioVolumeConverter.h" #include "PlaybackManager.h" using std::nothrow; @@ -49,9 +50,11 @@ ProxyAudioSupplier::ProxyAudioSupplier(PlaybackManager* playbackManager) , fPlaybackManager(playbackManager) , fVideoFrameRate(25.0) + , fVolume(1.0) , fSupplier(NULL) , fAdapter(NULL) + , fVolumeConverter(NULL) , fAudioResampler() { TRACE("ProxyAudioSupplier()\n"); @@ -62,6 +65,7 @@ ProxyAudioSupplier::~ProxyAudioSupplier() { TRACE("~ProxyAudioSupplier()\n"); delete fAdapter; + delete fVolumeConverter; } @@ -224,9 +228,30 @@ ProxyAudioSupplier::SetSupplier(AudioTrackSupplier* supplier, fVideoFrameRate = videoFrameRate; delete fAdapter; - fAdapter = new AudioAdapter(fSupplier, Format()); + delete fVolumeConverter; - fAudioResampler.SetSource(fAdapter); + fAdapter = new AudioAdapter(fSupplier, Format()); + fVolumeConverter = new AudioVolumeConverter(fAdapter, fVolume); + + fAudioResampler.SetSource(fVolumeConverter); +} + + +void +ProxyAudioSupplier::SetVolume(float volume) +{ + BAutolock _(fSupplierLock); + fVolume = volume; + if (fVolumeConverter) + fVolumeConverter->SetVolume(volume); +} + + +float +ProxyAudioSupplier::Volume() +{ + BAutolock _(fSupplierLock); + return fVolume; } diff --git a/src/apps/mediaplayer/supplier/ProxyAudioSupplier.h b/src/apps/mediaplayer/supplier/ProxyAudioSupplier.h index b265ff9d35..c48da00838 100644 --- a/src/apps/mediaplayer/supplier/ProxyAudioSupplier.h +++ b/src/apps/mediaplayer/supplier/ProxyAudioSupplier.h @@ -12,6 +12,7 @@ class AudioTrackSupplier; +class AudioVolumeConverter; class PlaybackManager; @@ -33,6 +34,8 @@ public: // ProxyAudioSupplier void SetSupplier(AudioTrackSupplier* supplier, float videoFrameRate); + void SetVolume(float volume); + float Volume(); private: int64 _AudioFrameForVideoFrame(int64 frame) const; @@ -50,9 +53,11 @@ private: PlaybackManager* fPlaybackManager; float fVideoFrameRate; + float fVolume; AudioTrackSupplier* fSupplier; AudioReader* fAdapter; + AudioVolumeConverter* fVolumeConverter; AudioResampler fAudioResampler; };