@@ -120,7 +120,7 @@ analyzer.prototype.getData = function getDataFunction(trackPath, callback) {
120120 * @param {type } callback
121121 * @returns {undefined }
122122 */
123- analyzer . prototype . getPCMValues = function getValuesFunction ( trackPath , callback ) {
123+ analyzer . prototype . getPeaks = function getValuesFunction ( trackPath , peaksAmount , callback ) {
124124
125125 this . getData ( trackPath , function ( error , trackData ) {
126126
@@ -129,7 +129,7 @@ analyzer.prototype.getPCMValues = function getValuesFunction(trackPath, callback
129129 console . log ( 'ffprobe track data: ' ) ;
130130 console . log ( trackData ) ;
131131
132- // get audio pcm
132+ // get audio pcm as 16bit little endians
133133 var ffmpegSpawn = childProcess . spawn (
134134 'ffmpeg' ,
135135 [
@@ -138,106 +138,113 @@ analyzer.prototype.getPCMValues = function getValuesFunction(trackPath, callback
138138 '-f' ,
139139 's16le' ,
140140 '-ac' ,
141- trackData . channels ,
141+ //trackData.channels,
142+ // put everything into one channel
143+ 1 ,
142144 '-acodec' ,
143145 'pcm_s16le' ,
144146 '-ar' ,
145147 trackData . sampleRate ,
146148 '-y' ,
147- 'pipe:1'
149+ 'pipe:1' // pipe to stdout
148150 ]
149151 ) ;
150152
151153 var stdoutOuputString = '' ;
152154 var stderrOuputString = '' ;
155+
156+ var samples = [ ] ;
153157
154- // TODO: uncomment for ffprobe
155- //ffmpegSpawn.stdout.setEncoding('utf8');
156-
157- var oddByte = null ;
158- var channel = 0 ;
159-
160- //var outputCounter = 0;
161-
162- var maxValue = 0 ;
163-
164- //var output = [];
165-
166- //var counter = 0;
167-
168- ffmpegSpawn . stdout . on ( 'data' , function ( data ) {
158+ ffmpegSpawn . stdout . on ( 'data' , function ( buffer ) {
159+
160+ // each buffer contains a certain amount of bytes (8bit)
161+ // https://trac.ffmpeg.org/wiki/audio%20types
169162
163+ // and we convert them to signed 16-bit little endians
170164 // http://nodejs.org/api/buffer.html#buffer_buf_readint16le_offset_noassert
171- // https://github.com/jhurliman/node-pcm/blob/master/lib/pcm.js
172-
173- var value ;
165+
166+
174167 var i ;
175- var dataLen = data . length ;
176- var percentageOfMax = 0 ;
177-
178- //counter++;
179-
180- for ( i = 0 ; i < dataLen ; i += 2 ) {
181-
182- value = data . readInt16LE ( i , true ) ;
183-
184- //channel = ++channel % 2;
185-
186- //console.log('B: ' + value + ' / ' + channel);
168+ var dataLen = buffer . length ;
169+
170+ // each buffer data contains 8bit but we read 16bit so i += 2
171+ for ( i = 0 ; i < dataLen ; i += 2 ) {
187172
188- //outputCounter++ ;
173+ var positiveSample = Math . abs ( buffer . readInt16LE ( i , false ) ) ;
189174
190- //if (value > maxValue) maxValue = value ;
175+ samples . push ( positiveSample ) ;
191176
192- // maxValue is 32767
177+ }
193178
194- // (value / maxValue)*100 = percentage of max
195- percentageOfMax = ( value / 32767 ) * 100 ;
179+ } ) ;
196180
197- //return false;
198-
199- //outputCounter++;
181+ ffmpegSpawn . stdout . on ( 'end' , function ( data ) {
200182
201- }
183+ console . log ( 'ffmpegSpawn stdout end' ) ;
202184
203- console . log ( i ) ;
185+ var samplesLength = samples . length ;
204186
205- //console.log('outputCounter: ' + outputCounter);
187+ if ( samplesLength > peaksAmount ) {
206188
207- //console.log(maxValue); // 32767
189+ var samplesCountPerPeak = Math . floor ( samplesLength / peaksAmount ) ;
190+ var peaks = [ ] ;
191+ var peaksInPercent = [ ] ;
208192
209- // get absolute value
210- //var absolutePercentageOfMaxMath = Math.abs(percentageOfMax);
193+ var i ;
194+ var start = 0 ;
195+ var end = start + samplesCountPerPeak ;
196+ var highestPeak = 0 ;
211197
212- //output.push(absolutePercentageOfMaxMath);
198+ for ( i = 0 ; i < peaksAmount ; i ++ ) {
199+
200+ var peaksGroup = samples . slice ( start , end ) ;
201+ var x ;
202+ var samplesSum = 0 ;
203+ var peaksGroupLength = peaksGroup . length ;
213204
214- //console.log(absolutePercentageOfMaxMath);
205+ for ( x = 0 ; x < peaksGroupLength ; x ++ ) {
215206
216- /*var bar = '' ;
207+ samplesSum += peaksGroup [ x ] ;
217208
218- for (i=0; i < absolutePercentageOfMaxMath/10; i++) {
209+ }
219210
220- bar += '*';
211+ peaks . push ( samplesSum ) ;
212+
213+ if ( samplesSum > highestPeak ) {
214+
215+ highestPeak = samplesSum ;
216+
217+ }
221218
222- }*/
219+ start += samplesCountPerPeak ;
220+ end += samplesCountPerPeak ;
223221
224- //console.log(bar);
222+ }
223+
224+ var y ;
225+ var peaksLength = peaks . length ;
225226
226- } ) ;
227+ for ( y = 0 ; y < peaksLength ; y ++ ) {
227228
228- ffmpegSpawn . stdout . on ( 'end' , function ( data ) {
229+ var peakInPercent = Math . round ( ( peaks [ y ] / highestPeak ) * 100 ) ;
229230
230- console . log ( 'ffmpegSpawn stdout end' ) ;
231- //console.log(counter);
232- //console.log(outputCounter);
231+ peaksInPercent . push ( peakInPercent ) ;
233232
234- if ( output . length > 0 ) {
233+ }
235234
236- callback ( false , output ) ;
235+ callback ( false , peaksInPercent ) ;
237236
238237 } else {
239-
240- callback ( 'no output recieved' ) ;
238+
239+ if ( samplesLength === 0 ) {
240+
241+ callback ( 'no output recieved' ) ;
242+
243+ } else if ( samplesLength < peaksAmount ) {
244+
245+ callback ( 'not enough peaks in this song for a full wave' ) ;
246+
247+ }
241248
242249 }
243250
0 commit comments