Commit 9f0986a7 authored by Matěj Laitl's avatar Matěj Laitl
Browse files

iPod collection: convert from ReplayGain to Sound Check and vice versa

By popular demand, we now convert ReplayGain values to Sound Check
values when transferring tracks to iPod. We also read Sound Check from
iPod and convert it to ReplayGain on-the-fly when playing a track off
an iPod in Amarok.

On the other hand, when transferring tracks from iPod to Amarok, Sound
Check from iPod is _not_ automatically copied (current limitation of
the ReplayGain implementation in Amarok), but Amarok picks up
ReplayGain information from meta-data stored inside the track. (Does
anyone know whether iTunes save Sound Check somewhere in song
meta-data?)

It is currently hard-coded that *track* ReplayGain is used (Sound Check
is not able to differentiate between track and album gains), this could
be configurable in future (but hey, micro-options!) or it could respect
Settings -> Replay Gain Mode (tricky, the setting would be read *only
when the song is being transferred to iPod*)

FEATURE: 142579
FIXED-IN: 2.6
DIGEST: volume normalization now works between Amarok and iPods
parent bbf58f7b
......@@ -7,6 +7,8 @@ Version 2.6-Beta 1
* album artist (if differs from artist), BPM, labels, last played time and
bitrate are now shown in playlist track tooltip (if not already displayed
in playlist)
* Volume normalization: ReplayGain is now converted to iPod Sound Check and
vice versa. (BR 142579)
CHANGES:
* libgpod requirement raised from 0.7.0 to 0.7.93 for better maintainability.
......
......@@ -69,6 +69,8 @@ extern "C" {
#include <QStringList>
#include <QTime>
#include <cmath>
using namespace Meta;
/// IpodHandler
......@@ -1616,6 +1618,17 @@ IpodHandler::libIsCompilation( const Meta::MediaDeviceTrackPtr &track )
return m_itdbtrackhash[ track ]->compilation != 0x0;
}
qreal
IpodHandler::libGetReplayGain( const MediaDeviceTrackPtr &track )
{
guint32 soundcheck = m_itdbtrackhash[ track ]->soundcheck;
if( soundcheck == 0 ) // libgpod: The value 0 is special, treated as "no Soundcheck"
return 0.0;
// libgpod: X = 1000 * 10 ^ (-.1 * Y)
// where Y is the adjustment value in dB and X is the value that goes into the SoundCheck field
return 30.0 - 10.0 * std::log10( soundcheck );
}
float
IpodHandler::usedCapacity() const
{
......@@ -1845,6 +1858,19 @@ IpodHandler::libSetIsCompilation( MediaDeviceTrackPtr &track, bool isCompilation
m_itdbtrackhash[ track ]->compilation = isCompilation ? 0x1 : 0x0;
}
void IpodHandler::libSetReplayGain( MediaDeviceTrackPtr &track, qreal newReplayGain )
{
guint32 soundcheck;
if( newReplayGain == 0.0 )
// libgpod: The value 0 is special, treated as "no Soundcheck"
soundcheck = 0;
else
// libgpod: X = 1000 * 10 ^ (-.1 * Y)
// where Y is the adjustment value in dB and X is the value that goes into the SoundCheck field
soundcheck = 1000 * std::pow( 10.0, -0.1 * newReplayGain );
m_itdbtrackhash[ track ]->soundcheck = soundcheck;
}
void
IpodHandler::libCreateTrack( const Meta::MediaDeviceTrackPtr& track )
{
......
......@@ -191,6 +191,7 @@ class IpodHandler : public Meta::MediaDeviceHandler
virtual void libSetType( Meta::MediaDeviceTrackPtr &track, const QString& type );
virtual void libSetPlayableUrl( Meta::MediaDeviceTrackPtr &destTrack, const Meta::TrackPtr &srcTrack );
virtual void libSetIsCompilation( Meta::MediaDeviceTrackPtr &track, bool isCompilation );
virtual void libSetReplayGain( Meta::MediaDeviceTrackPtr &track, qreal newReplayGain );
virtual void libSetCoverArt( Meta::MediaDeviceTrackPtr &track, const QImage &image );
virtual void libSetCoverArtPath( Meta::MediaDeviceTrackPtr &track, const QString &path );
......@@ -228,6 +229,7 @@ class IpodHandler : public Meta::MediaDeviceHandler
virtual QString libGetType( const Meta::MediaDeviceTrackPtr &track );
virtual KUrl libGetPlayableUrl( const Meta::MediaDeviceTrackPtr &track );
virtual bool libIsCompilation( const Meta::MediaDeviceTrackPtr &track );
virtual qreal libGetReplayGain( const Meta::MediaDeviceTrackPtr &track );
virtual QImage libGetCoverArt( const Meta::MediaDeviceTrackPtr &track );
virtual float usedCapacity() const;
......
......@@ -181,6 +181,12 @@ IpodReadCapability::libIsCompilation( const Meta::MediaDeviceTrackPtr &track )
return m_handler->libIsCompilation( track );
}
qreal
IpodReadCapability::libGetReplayGain( const Meta::MediaDeviceTrackPtr &track )
{
return m_handler->libGetReplayGain( track );
}
float
IpodReadCapability::usedCapacity() const
{
......
......@@ -64,6 +64,7 @@ class IpodReadCapability : public ReadCapability
virtual QString libGetType( const Meta::MediaDeviceTrackPtr &track );
virtual KUrl libGetPlayableUrl( const Meta::MediaDeviceTrackPtr &track );
virtual bool libIsCompilation( const Meta::MediaDeviceTrackPtr &track );
virtual qreal libGetReplayGain( const Meta::MediaDeviceTrackPtr &track );
virtual float usedCapacity() const;
virtual float totalCapacity() const;
......
......@@ -201,11 +201,17 @@ IpodWriteCapability::libSetPlayableUrl( Meta::MediaDeviceTrackPtr &destTrack, co
}
void
IpodWriteCapability::libSetIsCompilation(Meta::MediaDeviceTrackPtr& track, bool isCompilation)
IpodWriteCapability::libSetIsCompilation( Meta::MediaDeviceTrackPtr &track, bool isCompilation )
{
m_handler->libSetIsCompilation( track, isCompilation );
}
void
IpodWriteCapability::libSetReplayGain( Meta::MediaDeviceTrackPtr &track, qreal newReplayGain )
{
m_handler->libSetReplayGain( track, newReplayGain );
}
void
IpodWriteCapability::libSetCoverArt( Meta::MediaDeviceTrackPtr &track, const QImage &cover )
{
......
......@@ -71,6 +71,7 @@ class IpodWriteCapability : public WriteCapability
virtual void libSetType( Meta::MediaDeviceTrackPtr &track, const QString& type );
virtual void libSetPlayableUrl( Meta::MediaDeviceTrackPtr &destTrack, const Meta::TrackPtr &srcTrack );
virtual void libSetIsCompilation( Meta::MediaDeviceTrackPtr &track, bool isCompilation );
virtual void libSetReplayGain( Meta::MediaDeviceTrackPtr &track, qreal newReplayGain );
virtual void libSetCoverArt( Meta::MediaDeviceTrackPtr &track, const QImage &cover );
virtual void prepareToCopy();
......
......@@ -318,6 +318,29 @@ MediaDeviceTrack::setLastPlayed( const QDateTime &newTime )
m_lastPlayed = newTime;
}
qreal
MediaDeviceTrack::replayGain( ReplayGainTag mode ) const
{
/* no known non-UMS portable media player is able to differentiante between different
* replay gain modes (track & album), so store only one value */
switch( mode ) {
case Meta::ReplayGain_Track_Gain:
case Meta::ReplayGain_Album_Gain:
return m_replayGain;
case Meta::ReplayGain_Track_Peak:
case Meta::ReplayGain_Album_Peak:
// no default label so that compiler emits a warning when new enum value is added
break;
}
return 0.0;
}
void
MediaDeviceTrack::setReplayGain( qreal newReplayGain )
{
m_replayGain = newReplayGain;
}
QString
MediaDeviceTrack::type() const
{
......
......@@ -119,6 +119,10 @@ class MEDIADEVICECOLLECTION_EXPORT MediaDeviceTrack : public Meta::Track
virtual int playCount() const;
void setPlayCount( const int newCount );
virtual qreal replayGain( ReplayGainTag mode ) const;
/* Set the track replay gain (other types unsupported) */
void setReplayGain( qreal newReplayGain );
virtual QString type() const;
virtual void prepareToPlay();
......@@ -174,6 +178,7 @@ class MEDIADEVICECOLLECTION_EXPORT MediaDeviceTrack : public Meta::Track
QDateTime m_lastPlayed;
int m_rating;
qreal m_bpm;
qreal m_replayGain;
QString m_displayUrl;
KUrl m_playableUrl;
};
......
......@@ -97,6 +97,7 @@ MediaDeviceHandler::getBasicMediaDeviceTrackInfo( const Meta::MediaDeviceTrackPt
destTrack->setPlayCount( m_rc->libGetPlayCount( srcTrack ) );
destTrack->setLastPlayed( m_rc->libGetLastPlayed( srcTrack ) );
destTrack->setRating( m_rc->libGetRating( srcTrack ) );
destTrack->setReplayGain( m_rc->libGetReplayGain( srcTrack ) );
destTrack->setPlayableUrl( m_rc->libGetPlayableUrl( srcTrack ) );
......@@ -119,6 +120,8 @@ MediaDeviceHandler::getBasicMediaDeviceTrackInfo( const Meta::TrackPtr &srcTrack
destTrack->setPlayCount( srcTrack->playCount() );
destTrack->setLastPlayed( srcTrack->lastPlayed() );
destTrack->setRating( srcTrack->rating() );
// MediaDeviceTrack stores only track gain:
destTrack->setReplayGain( srcTrack->replayGain( Meta::ReplayGain_Track_Gain ) );
destTrack->setPlayableUrl( srcTrack->playableUrl() );
......@@ -191,6 +194,8 @@ MediaDeviceHandler::setBasicMediaDeviceTrackInfo( const Meta::TrackPtr& srcTrack
m_wc->libSetPlayCount( destTrack, srcTrack->playCount() );
m_wc->libSetLastPlayed( destTrack, srcTrack->lastPlayed() );
m_wc->libSetRating( destTrack, srcTrack->rating() );
// MediaDeviceTrack stores only track gain:
m_wc->libSetReplayGain( destTrack, srcTrack->replayGain( Meta::ReplayGain_Track_Gain ) );
m_wc->libSetType( destTrack, srcTrack->type() );
//libSetPlayableUrl( destTrack, srcTrack );
}
......
......@@ -29,4 +29,10 @@ Handler::ReadCapability::libIsCompilation( const Meta::MediaDeviceTrackPtr &trac
return false;
}
qreal Handler::ReadCapability::libGetReplayGain( const Meta::MediaDeviceTrackPtr &track )
{
Q_UNUSED( track )
return 0.0;
}
#include "ReadCapability.moc"
......@@ -106,6 +106,7 @@ class MEDIADEVICECOLLECTION_EXPORT ReadCapability : public Handler::Capability
virtual QString libGetType( const Meta::MediaDeviceTrackPtr &track ) = 0;
virtual KUrl libGetPlayableUrl( const Meta::MediaDeviceTrackPtr &track ) = 0;
virtual bool libIsCompilation( const Meta::MediaDeviceTrackPtr &track );
virtual qreal libGetReplayGain( const Meta::MediaDeviceTrackPtr &track );
/**
* Get used capacity on the device, in bytes. Returns 0.0 if capacity information
......
......@@ -29,4 +29,11 @@ Handler::WriteCapability::libSetIsCompilation( Meta::MediaDeviceTrackPtr &track,
// provide default implementation so that MTP collection doesn't need to override.
}
void
Handler::WriteCapability::libSetReplayGain( Meta::MediaDeviceTrackPtr &track, qreal newReplayGain )
{
Q_UNUSED( track )
Q_UNUSED( newReplayGain )
}
#include "WriteCapability.moc"
......@@ -156,6 +156,7 @@ class MEDIADEVICECOLLECTION_EXPORT WriteCapability : public Handler::Capability
virtual void libSetType( Meta::MediaDeviceTrackPtr &track, const QString& type ) = 0;
virtual void libSetPlayableUrl( Meta::MediaDeviceTrackPtr &destTrack, const Meta::TrackPtr &srcTrack ) = 0;
virtual void libSetIsCompilation( Meta::MediaDeviceTrackPtr &track, bool isCompilation );
virtual void libSetReplayGain( Meta::MediaDeviceTrackPtr &track, qreal newReplayGain );
virtual void libSetCoverArt( Meta::MediaDeviceTrackPtr &track, const QImage &cover ) = 0;
};
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment