d@0
|
1 /*
|
d@0
|
2 ==============================================================================
|
d@0
|
3
|
d@0
|
4 AudioReader.cpp
|
d@0
|
5 Created: 27 Aug 2014 3:17:10pm
|
d@0
|
6 Author: david.ronan
|
d@0
|
7
|
d@0
|
8 ==============================================================================
|
d@0
|
9 */
|
d@0
|
10
|
d@0
|
11
|
d@0
|
12
|
d@0
|
13
|
d@0
|
14 #include "AudioReader.h"
|
d@0
|
15 #include "WriteCSV.h"
|
d@0
|
16 #include <iostream>
|
d@0
|
17 #include <vector>
|
d@0
|
18
|
d@0
|
19 #define ENERGYSEARCHTIME 3
|
d@0
|
20 #define SAMPLERATE 22050.0f
|
d@0
|
21
|
d@0
|
22 AudioReader::AudioReader()
|
d@0
|
23 {
|
d@0
|
24 m_formatManager.registerBasicFormats();
|
d@0
|
25 };
|
d@0
|
26
|
d@0
|
27 AudioReader::~AudioReader()
|
d@0
|
28 {
|
d@0
|
29
|
d@0
|
30 };
|
d@0
|
31
|
d@0
|
32 std::vector<FeatureData> AudioReader::Read(AudioFileData audioFileData, float poolTimeSecs, int analysisWindowSize)
|
d@0
|
33 {
|
d@0
|
34 WriteCSV writeCSV = WriteCSV();
|
d@0
|
35 std::vector<FeatureData> featureData = std::vector<FeatureData>();
|
d@0
|
36 std::string CSVFileName = "..\\FeatureData" + writeCSV.currentDateTime();
|
d@0
|
37
|
d@0
|
38 vector<string> audioFileNames = audioFileData.GetFileNames();
|
d@0
|
39 vector<string> labels = audioFileData.GetLabels();
|
d@0
|
40
|
d@0
|
41 //AudioSourceFeatureExtractor audioSourceFeatureExtractor = AudioSourceFeatureExtractor();
|
d@0
|
42 m_AudioSourceFeatureExtractor.Initialise(SAMPLERATE);
|
d@0
|
43
|
d@0
|
44 for(size_t i=0; i<audioFileNames.size(); i++)
|
d@0
|
45 {
|
d@0
|
46 float percentcomplete = (float)i / (float)audioFileNames.size() * 100.0f;
|
d@0
|
47
|
d@0
|
48 std::string outputStr = "Extracting features for " + audioFileNames[i] + "\n" + std::to_string(percentcomplete) + "% complete...";
|
d@0
|
49 cout << outputStr;
|
d@0
|
50
|
d@0
|
51 //Create file from our audio data
|
d@0
|
52 File audioFile(audioFileNames[i].c_str());
|
d@0
|
53
|
d@0
|
54 AudioFormatReader* m_audioFileReader = m_formatManager.createReaderFor(audioFile);
|
d@0
|
55
|
d@0
|
56 if(m_audioFileReader != NULL)
|
d@0
|
57 {
|
d@0
|
58 m_fSampleRate = (float)(m_audioFileReader->sampleRate);
|
d@0
|
59 m_iLengthInSamples = (int)m_audioFileReader->lengthInSamples;
|
d@0
|
60 m_iNumOfChannels = m_audioFileReader->numChannels;
|
d@0
|
61
|
d@0
|
62 if (m_fSampleRate != 22050.0f)
|
d@0
|
63 {
|
d@0
|
64 cout << "\n\n\nERROR: File is not the required 22050 Hz sample rate.!!!\n\n\n";
|
d@0
|
65 }
|
d@0
|
66
|
d@0
|
67 //Get loudest 30 secs. of audio
|
d@0
|
68 int numOfSamplesToCollect = (int)(analysisWindowSize * m_fSampleRate);
|
d@0
|
69
|
d@0
|
70 if(m_iLengthInSamples <= numOfSamplesToCollect)
|
d@0
|
71 {
|
d@0
|
72 numOfSamplesToCollect = m_iLengthInSamples;
|
d@0
|
73 }
|
d@0
|
74
|
d@0
|
75 //Length of the full track in stereo;
|
d@0
|
76 int* destSamples[2] = {0};
|
d@0
|
77 int* L = new int[(size_t)(m_iLengthInSamples)];
|
d@0
|
78 memset(L, 0, (size_t)m_iLengthInSamples*sizeof(float));
|
d@0
|
79 destSamples[0]=L;
|
d@0
|
80 destSamples[1]=L;
|
d@0
|
81
|
d@0
|
82 //30 sec clips to check energy levels
|
d@0
|
83 float* destSamplesFloat = new float[(size_t)numOfSamplesToCollect];
|
d@0
|
84 memset(destSamplesFloat, 0, (size_t)numOfSamplesToCollect*sizeof(float));
|
d@0
|
85
|
d@0
|
86 ////30 sec clips to check energy levels
|
d@0
|
87 //float* destSamplesFloatLoudest = new float[(size_t)numOfSamplesToCollect];
|
d@0
|
88 //memset(destSamplesFloatLoudest, 0, (size_t)numOfSamplesToCollect*sizeof(float));
|
d@0
|
89
|
d@0
|
90 int timesToLoop = 0;
|
d@0
|
91
|
d@0
|
92 if(m_iLengthInSamples == numOfSamplesToCollect)
|
d@0
|
93 {
|
d@0
|
94 timesToLoop = 1;
|
d@0
|
95 }
|
d@0
|
96 else
|
d@0
|
97 {
|
d@0
|
98 timesToLoop = (int)((m_iLengthInSamples - numOfSamplesToCollect) / (ENERGYSEARCHTIME * m_fSampleRate));
|
d@0
|
99 }
|
d@0
|
100
|
d@0
|
101 std::vector<float> thirtySecEnergy = std::vector<float>();
|
d@0
|
102
|
d@0
|
103 //float loudestEnergy = 0.0;
|
d@0
|
104
|
d@0
|
105 m_audioFileReader->readSamples(destSamples, 2, 0, 0, m_iLengthInSamples);
|
d@0
|
106
|
d@0
|
107 for(int j=0; j < timesToLoop;j++)
|
d@0
|
108 {
|
d@0
|
109 float fSum=0.f;
|
d@0
|
110
|
d@0
|
111 for(int n=0; n<numOfSamplesToCollect; n++)
|
d@0
|
112 {
|
d@0
|
113 //Sum to mono if needed and workout the energy for each 30 sec. frame
|
d@0
|
114 if(m_iNumOfChannels > 1)
|
d@0
|
115 {
|
d@0
|
116 destSamplesFloat[n] = ((float)((destSamples[0][int(j * ENERGYSEARCHTIME * m_fSampleRate) + n] + destSamples[1][int( j * ENERGYSEARCHTIME * m_fSampleRate) + n]) / 2) / (0x7fffffff));
|
d@0
|
117 }
|
d@0
|
118 else
|
d@0
|
119 {
|
d@0
|
120 destSamplesFloat[n] = ((float)(destSamples[0][int(j * ENERGYSEARCHTIME * m_fSampleRate) + n]) / (0x7fffffff));
|
d@0
|
121 }
|
d@0
|
122
|
d@0
|
123 fSum+=(destSamplesFloat[n] * destSamplesFloat[n]);
|
d@0
|
124 }
|
d@0
|
125
|
d@0
|
126 //Normalise and push onto the list of 30 sec clips.
|
d@0
|
127 fSum /= numOfSamplesToCollect;
|
d@0
|
128
|
d@0
|
129 //if (fSum > loudestEnergy)
|
d@0
|
130 //{
|
d@0
|
131 // loudestEnergy = fSum;
|
d@0
|
132 // destSamplesFloatLoudest = destSamplesFloat;
|
d@0
|
133 //}
|
d@0
|
134
|
d@0
|
135 thirtySecEnergy.push_back(fSum);
|
d@0
|
136 }
|
d@0
|
137
|
d@0
|
138 //Find the index of the section with the most energy
|
d@0
|
139 int maxIdx = std::distance(thirtySecEnergy.begin(), max_element(thirtySecEnergy.begin(), thirtySecEnergy.end()));
|
d@0
|
140
|
d@0
|
141 int* thirtySecSamples[2] = {0};
|
d@0
|
142 int* L30 = new int[(size_t)numOfSamplesToCollect];
|
d@0
|
143 memset(L30, 0, (size_t)numOfSamplesToCollect*sizeof(float));
|
d@0
|
144 thirtySecSamples[0]=L30; //Left channel
|
d@0
|
145 thirtySecSamples[1]=L30; //Left right
|
d@0
|
146
|
d@0
|
147 //Read the 30 secs. in
|
d@0
|
148 m_audioFileReader->readSamples(thirtySecSamples, 2, 0, int(maxIdx * ENERGYSEARCHTIME * m_fSampleRate), numOfSamplesToCollect);
|
d@0
|
149 memset(destSamplesFloat, 0, (size_t)numOfSamplesToCollect*sizeof(float));
|
d@0
|
150
|
d@0
|
151 for(int n=0; n<numOfSamplesToCollect; n++)
|
d@0
|
152 {
|
d@0
|
153 //Sum to mono if needed
|
d@0
|
154 if(m_iNumOfChannels > 1)
|
d@0
|
155 {
|
d@0
|
156 destSamplesFloat[n] = ((float)((thirtySecSamples[0][n] + thirtySecSamples[1][n]) / 2) / (0x7fffffff));
|
d@0
|
157 }
|
d@0
|
158 else
|
d@0
|
159 {
|
d@0
|
160 destSamplesFloat[n] = ((float)(thirtySecSamples[0][n]) / (0x7fffffff));
|
d@0
|
161 }
|
d@0
|
162 }
|
d@0
|
163
|
d@0
|
164 std::vector<ObservationData> newObs = m_AudioSourceFeatureExtractor.Process(destSamplesFloat, numOfSamplesToCollect);
|
d@0
|
165
|
d@0
|
166 FeatureData newFeature = FeatureData(newObs, labels[i], audioFileNames[i], m_fSampleRate, FFTSIZE, (float)numOfSamplesToCollect, poolTimeSecs);
|
d@0
|
167
|
d@0
|
168 writeCSV.Write(CSVFileName, newFeature);
|
d@0
|
169
|
d@0
|
170 //Update the screen information;
|
d@0
|
171 cout << cout << string(outputStr.length(),'\b');
|
d@0
|
172
|
d@0
|
173 //Cleanup
|
d@0
|
174 if(L != NULL)
|
d@0
|
175 {
|
d@0
|
176 delete[] L;
|
d@0
|
177 L = nullptr;
|
d@0
|
178 }
|
d@0
|
179
|
d@0
|
180 if(destSamplesFloat != NULL)
|
d@0
|
181 {
|
d@0
|
182 delete[] destSamplesFloat;
|
d@0
|
183 destSamplesFloat = nullptr;
|
d@0
|
184 //destSamplesFloatLoudest = nullptr;
|
d@0
|
185 }
|
d@0
|
186
|
d@0
|
187 //if(destSamplesFloatLoudest != NULL)
|
d@0
|
188 //{
|
d@0
|
189 // delete[] destSamplesFloatLoudest;
|
d@0
|
190 //
|
d@0
|
191 //}
|
d@0
|
192 }
|
d@0
|
193 else
|
d@0
|
194 {
|
d@0
|
195 cout << "\n\n\nERROR: Could not find file!!!\n\n\n";
|
d@0
|
196 }
|
d@0
|
197
|
d@0
|
198 //Cleanup
|
d@0
|
199 if(m_audioFileReader != NULL)
|
d@0
|
200 {
|
d@0
|
201 delete[] m_audioFileReader;
|
d@0
|
202 m_audioFileReader = nullptr;
|
d@0
|
203 }
|
d@0
|
204 }
|
d@0
|
205
|
d@0
|
206 m_AudioSourceFeatureExtractor.Finalize();
|
d@0
|
207
|
d@0
|
208 return featureData;
|
d@0
|
209 }; |