getPitchFromAudioData method
Implementation
Future<double> getPitchFromAudioData(Uint8List audioData) async {
// Web browsers may deliver stereo (2-ch interleaved int16) even when mono
// is requested. Down-mix to mono so the pitch detector sees the correct
// period — otherwise every other sample belongs to a different channel,
// which halves the apparent frequency (one octave down).
if (kIsWeb) {
_accumulatedData.addAll(_stereoToMono(audioData));
} else {
_accumulatedData.addAll(audioData);
}
const int bytesPerSample = 2;
double pitch = 0;
int neededBytes = NeomGeneratorConstants.neededSamples * bytesPerSample;
// On web, use the auto-detected sample rate from _calibrateWebSampleRate().
// On mobile, use the requested rate (OS respects it).
final double effectiveSampleRate = kIsWeb
? _webSampleRate
: NeomGeneratorConstants.sampleRate.toDouble();
while (_accumulatedData.length >= neededBytes) {
final chunk = _accumulatedData.sublist(0, neededBytes);
_accumulatedData.removeRange(0, neededBytes);
final pitchDetectorDart = PitchDetector(
audioSampleRate: effectiveSampleRate,
bufferSize: NeomGeneratorConstants.neededSamples,
);
try {
final chunkAsUint8List = Uint8List.fromList(chunk);
PitchDetectorResult pitchResult = await pitchDetectorDart.getPitchFromIntBuffer(chunkAsUint8List);
pitch = pitchResult.pitch.roundToDouble();
} catch (e, st) {
NeomErrorLogger.recordError(e, st, module: 'neom_generator', operation: 'getPitchFromAudioData');
}
}
return pitch;
}