22 #include "MASoundData.hpp" 24 #include "MALossyConverter.hpp" 26 #include <MCSampleStatistics.hpp> 28 #include <libresample.h> 32 #include <boost/algorithm/string/predicate.hpp> 33 #include <boost/scoped_ptr.hpp> 39 WaveFile AudioFile(file_name);
41 if (AudioFile.GetBitsPerSample() != 16 || (int)AudioFile.GetAudioFormat() != 1 ||
42 AudioFile.GetNumChannels() < 1 || AudioFile.GetNumChannels() > 2)
44 MC_WARNING(
"Only 16 bit mono or stereo PCM Wave files are supported (file: %s)!", file_name.c_str());
47 float Divider = (float)2*AudioFile.GetNumChannels()*AudioFile.GetSampleRate() / 1000;
54 MC::DoubleList& right_channel,
int compression,
int bitrate)
58 int FileSampleRate = 0;
61 if (boost::algorithm::iends_with(file_name,
".wav"))
63 WaveFile AudioFile(file_name);
65 if (AudioFile.GetBitsPerSample() != 16 || (int)AudioFile.GetAudioFormat() != 1 ||
66 AudioFile.GetNumChannels() < 1 || AudioFile.GetNumChannels() > 2 ||
67 AudioFile.GetSampleRate() == 0)
69 MC_WARNING(
"Only 16 bit mono or stereo PCM Wave files are supported (file: %s)!", file_name.c_str());
72 FileSampleRate = (int)AudioFile.GetSampleRate();
73 Channels = AudioFile.GetNumChannels();
74 FileData->Allocate(AudioFile.GetDataSize());
75 memcpy(FileData->GetData(), AudioFile.GetData(), (int)AudioFile.GetDataSize());
77 if (boost::algorithm::iends_with(file_name,
".ogg") || boost::algorithm::iends_with(file_name,
".mp3"))
81 EncodedData->LoadFromFile(file_name);
82 if (boost::algorithm::iends_with(file_name,
".ogg"))
86 if (boost::algorithm::iends_with(file_name,
".mp3"))
90 if (Channels < 1 || Channels > 2 || FileSampleRate == 0)
92 MC_WARNING(
"Only mono or stereo Ogg Vorbis/mp3 files are supported (file: %s)!", file_name.c_str());
97 MC::BinaryDataSPtr CompressedFileData;
98 MC::DoubleList FileDataDouble;
100 if (compression == 1)
104 if (!CompressedFileData.get())
106 MC_WARNING(
"Lossy Ogg Vorbis encoding failed: %s\n", file_name.c_str());
111 if (compression == 2)
115 if (!CompressedFileData.get())
117 MC_WARNING(
"Lossy mp3 encoding failed: %s\n", file_name.c_str());
120 FileSampleRate, Channels));
127 left_channel = FileDataDouble;
128 right_channel.clear();
133 FileDataDouble.clear();
138 if (!right_channel.empty())
147 MC::DoubleList NewData;
149 NewData.resize(raw_data.
GetSize() / 2);
150 for (
int i = 0; i < raw_data.
GetSize() / 2; ++i)
152 NewData[i] = (double)(((
int)raw_data.
GetData()[i*2+1] << 8) | (
int)raw_data.
GetData()[i*2]) / ((
float)0x8000);
163 const unsigned int Count =
MCMax(left_channel.size(), right_channel.size());
165 RawData =
new MCBinaryData((
int)(left_channel.size()+right_channel.size())*2);
166 for (
unsigned int i = 0; i < Count; ++i)
170 if (i < left_channel.size())
172 Data = left_channel[i];
176 RawData->AddUChar((
unsigned char)((
int)(Data*32768) % 256));
177 RawData->AddUChar((
unsigned char)((
int)(Data*32768) / 256));
179 if (right_channel.size() == 0)
183 if (i < right_channel.size())
185 Data = right_channel[i];
189 RawData->AddUChar((
unsigned char)((
int)(Data*32768) % 256));
190 RawData->AddUChar((
unsigned char)((
int)(Data*32768) / 256));
198 int WindowSize = 10*(int)frequency / 10000;
200 boost::scoped_ptr<MCSamples<double> > PowerSamples(
new MCSamples<double>(WindowSize, *PowerStatistic));
202 while ((
int)audio_data.size() > WindowSize*2)
204 int DataSize = audio_data.size();
205 float LeadingPower = 0;
206 float TrailingPower = 0;
208 for (
int i = 0; i < WindowSize; ++i)
210 *PowerSamples << audio_data[i];
212 LeadingPower = PowerStatistic->
GetResult();
213 for (
int i = 0; i < WindowSize; ++i)
215 *PowerSamples << audio_data[DataSize-i];
217 TrailingPower = PowerStatistic->
GetResult();
218 if (LeadingPower >= 10 && TrailingPower >= 10)
220 if (LeadingPower <= 10)
221 audio_data.erase(audio_data.begin(), audio_data.begin()+WindowSize);
222 if (TrailingPower <= 10)
223 audio_data.erase(audio_data.end()-WindowSize, audio_data.end());
230 if (audio_data.empty())
231 return MC::DoubleList();
234 MC::FloatList OldData;
235 double Factor = (double)new_frequency / original_frequency;
237 OldData.resize(audio_data.size());
238 for (
unsigned int i = 0; i < OldData.size(); ++i)
240 OldData[i] = (float)audio_data[i];
243 int MaxDataSize = (int)(ceil((
float)audio_data.size()*Factor)+100);
244 MC::FloatList ResampleData;
245 MC::DoubleList FinalData;
246 void* handle = resample_open(1, Factor, Factor);
247 int UsedBytes = 0, OutputCount = 0;
249 ResampleData.resize(MaxDataSize);
250 OutputCount = resample_process(handle, Factor, &OldData[0], OldData.size(), 0, &UsedBytes,
251 &ResampleData[0], ResampleData.size());
252 resample_close(handle);
253 FinalData.resize(OutputCount);
254 for (
unsigned int i = 0; i < FinalData.size(); ++i)
256 FinalData[i] = (float)ResampleData[i];
264 unsigned int WindowSize = 0;
266 for (WindowSize = 1; WindowSize < frequency*30 / 1000; WindowSize *= 2)
278 MC_WARNING(
"The data count of the channels are not equal and divisible by 2 (left: %d, right: %d)",
283 char* StereoDataPtr = (
char*)stereo.
GetData();
284 char* LeftChannelDataPtr = (
char*)left_channel.
GetData();
285 char* RightChannelDataPtr = (
char*)right_channel.
GetData();
287 for (
int i = 0; i < stereo.
GetSize() / 4; ++i)
289 memcpy(StereoDataPtr, LeftChannelDataPtr, 2);
290 memcpy(StereoDataPtr+2, RightChannelDataPtr, 2);
291 LeftChannelDataPtr += 2;
292 RightChannelDataPtr += 2;
301 if (audio_data.empty())
311 return 20*log10(Peak);
320 return signal_power_db-noise_power_db;
static float CalculatePowerDb(const MC::DoubleList &audio_data)
Calculate the power level of the signal in dB.
static MCBinaryData * ConvertDoubleToRaw(MC::DoubleList &left_channel, MC::DoubleList &right_channel)
Convert double lists back to raw audio data.
static MCBinaryData * EncodeToMp3(const MCBinaryData &raw_data, const int sample_rate, const int channels, const int quality)
Encode raw audio data to mp3.
bool IsEmpty() const
Check if the binary data is not filled with invalid data.
static unsigned int GetWindowSize(unsigned int frequency)
Get window size for a given frequency.
static const int SampleRateOnAIBO
Sample rate for audio processing on AIBO.
static void RemoveLeadingTrailingSilence(MC::DoubleList &audio_data, unsigned int sample_rate)
Remove leading and trailing silences from the audio data.
static int GetFileDuration(const std::string &file_name)
Get audio duration of a file.
int MCGetFileSize(const std::string &file_name)
Get file size.
virtual float GetResult()=0
Get the current result of the statistic.
float MCCalculateVectorStatistic(const std::vector< T > &vector, MCSampleStatistic< T > &statistic)
Calculate a statistic over a vector.
#define MC_WARNING(...)
Warning macro.
static MCBinaryData * DecodeFromOggVorbis(MCBinaryData &ogg_data, int &sample_rate, int &channels)
Decode Ogg Vorbis data to raw audio.
static bool Join(const MCBinaryData &left_channel, const MCBinaryData &right_channel, MCBinaryData &stereo)
Join stereo track into two channels.
T MCAbs(const T &value)
Calculate absolute value.
void Allocate(int size)
Allocate a certain data size.
static float CalculateSnr(const float signal_power_db, const float noise_power_db)
Calculate signal-to-noise ratio (SNR)
static MC::DoubleList ConvertToDouble(const MCBinaryData &raw_data)
Convert audio data to a double list.
Sample statistic base class.
bool MCIsFloatInfinity(const float value)
Check a value for float infinity.
static MC::DoubleList Resample(const MC::DoubleList &audio_data, int original_frequency, int new_frequency)
Resample audio data.
static bool LoadFromFile(const std::string &file_name, MC::DoubleList &left_channel, MC::DoubleList &right_channel, int compression=0, int bitrate=0)
Load audio data from a wav file.
static MCBinaryData * DecodeFromMp3(MCBinaryData &mp3_data, unsigned int orig_size, int &sample_rate, int &channels)
Decode mp3 data to raw audio.
U MCNthItemsFromContainer(const U &container, unsigned int n_th, unsigned int period)
Get items from n-th indexes of a container.
unsigned char * GetData() const
Get direct access to the binary data.
float MCFloatInfinity()
Get float infinity.
const T MCMax(const U &container)
Get the maximal value of a container.
static MCBinaryData * EncodeToOggVorbis(const MCBinaryData &raw_data, const int sample_rate, const int channels, const int quality)
Encode raw audio data to Ogg Vorbis.
int GetSize() const
Get binary data size.