1 /***************************************************************************
2 copyright : (C) 2002 - 2008 by Scott Wheeler
3 email : wheeler@kde.org
4 ***************************************************************************/
6 /***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
29 #include "relativevolumeframe.h"
31 using namespace TagLib;
32 using namespace ID3v2;
34 static inline int bitsToBytes(int i)
36 return i % 8 == 0 ? i / 8 : (i - i % 8) / 8 + 1;
41 ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
43 RelativeVolumeFrame::ChannelType channelType;
44 short volumeAdjustment;
45 RelativeVolumeFrame::PeakVolume peakVolume;
48 class RelativeVolumeFrame::RelativeVolumeFramePrivate
51 String identification;
52 Map<ChannelType, ChannelData> channels;
55 ////////////////////////////////////////////////////////////////////////////////
57 ////////////////////////////////////////////////////////////////////////////////
59 RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2")
61 d = new RelativeVolumeFramePrivate;
64 RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data)
66 d = new RelativeVolumeFramePrivate;
70 RelativeVolumeFrame::~RelativeVolumeFrame()
75 String RelativeVolumeFrame::toString() const
77 return d->identification;
80 List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
84 Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
85 for(; it != d->channels.end(); ++it)
86 l.append((*it).first);
93 RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const
100 void RelativeVolumeFrame::setChannelType(ChannelType)
105 short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const
107 return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0;
110 short RelativeVolumeFrame::volumeAdjustmentIndex() const
112 return volumeAdjustmentIndex(MasterVolume);
115 void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type)
117 d->channels[type].volumeAdjustment = index;
120 void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index)
122 setVolumeAdjustmentIndex(index, MasterVolume);
125 float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const
127 return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0;
130 float RelativeVolumeFrame::volumeAdjustment() const
132 return volumeAdjustment(MasterVolume);
135 void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type)
137 d->channels[type].volumeAdjustment = short(adjustment * float(512));
140 void RelativeVolumeFrame::setVolumeAdjustment(float adjustment)
142 setVolumeAdjustment(adjustment, MasterVolume);
145 RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const
147 return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume();
150 RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const
152 return peakVolume(MasterVolume);
155 void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type)
157 d->channels[type].peakVolume = peak;
160 void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak)
162 setPeakVolume(peak, MasterVolume);
165 String RelativeVolumeFrame::identification() const
167 return d->identification;
170 void RelativeVolumeFrame::setIdentification(const String &s)
172 d->identification = s;
175 ////////////////////////////////////////////////////////////////////////////////
177 ////////////////////////////////////////////////////////////////////////////////
179 void RelativeVolumeFrame::parseFields(const ByteVector &data)
182 d->identification = readStringField(data, String::Latin1, &pos);
184 // Each channel is at least 4 bytes.
186 while(pos <= (int)data.size() - 4) {
189 ChannelType type = ChannelType(data[pos]);
192 ChannelData &channel = d->channels[type];
194 channel.volumeAdjustment = data.mid(pos, 2).toShort();
197 channel.peakVolume.bitsRepresentingPeak = data[pos];
200 int bytes = bitsToBytes(channel.peakVolume.bitsRepresentingPeak);
201 channel.peakVolume.peakVolume = data.mid(pos, bytes);
206 ByteVector RelativeVolumeFrame::renderFields() const
210 data.append(d->identification.data(String::Latin1));
211 data.append(textDelimiter(String::Latin1));
213 Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
215 for(; it != d->channels.end(); ++it) {
216 ChannelType type = (*it).first;
217 const ChannelData &channel = (*it).second;
219 data.append(char(type));
220 data.append(ByteVector::fromShort(channel.volumeAdjustment));
221 data.append(char(channel.peakVolume.bitsRepresentingPeak));
222 data.append(channel.peakVolume.peakVolume);
228 ////////////////////////////////////////////////////////////////////////////////
230 ////////////////////////////////////////////////////////////////////////////////
232 RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h)
234 d = new RelativeVolumeFramePrivate;
235 parseFields(fieldData(data));