godcrm/god_frame/lib/features/frame/data/audio_upsampler.dart
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

46 lines
1.8 KiB
Dart

import 'dart:typed_data';
/// Upsamples PCM audio from 8kHz to 16kHz using linear interpolation.
/// Required because Frame captures at 8kHz but Gemini expects 16kHz.
class AudioUpsampler {
/// Upsample PCM16 (signed 16-bit samples) from 8kHz to 16kHz.
/// Uses linear interpolation to double the sample rate.
static Uint8List upsample8kTo16k(Uint8List input) {
// Input: PCM16 at 8kHz (2 bytes per sample)
final inputSamples = Int16List.view(input.buffer, input.offsetInBytes, input.lengthInBytes ~/ 2);
final outputSamples = Int16List(inputSamples.length * 2);
for (int i = 0; i < inputSamples.length - 1; i++) {
final current = inputSamples[i];
final next = inputSamples[i + 1];
outputSamples[i * 2] = current;
outputSamples[i * 2 + 1] = current + ((next - current) ~/ 2);
}
// Last sample: duplicate
if (inputSamples.isNotEmpty) {
outputSamples[outputSamples.length - 2] = inputSamples.last;
outputSamples[outputSamples.length - 1] = inputSamples.last;
}
return Uint8List.view(outputSamples.buffer);
}
/// Convert 8-bit unsigned PCM (from Frame) to 16-bit signed PCM.
/// Frame sends 8-bit unsigned PCM at 8kHz.
/// Output: 16-bit signed PCM suitable for Gemini (after upsampling).
static Uint8List pcm8Topcm16(Uint8List pcm8) {
final pcm16 = Int16List(pcm8.length);
for (int i = 0; i < pcm8.length; i++) {
// Convert unsigned 8-bit (0-255) to signed 16-bit (-32768 to 32767)
pcm16[i] = ((pcm8[i] - 128) * 256).clamp(-32768, 32767);
}
return Uint8List.view(pcm16.buffer);
}
/// Full pipeline: Frame 8-bit 8kHz → 16-bit 16kHz PCM for Gemini.
static Uint8List frameToGemini(Uint8List frameAudio) {
final pcm16 = pcm8Topcm16(frameAudio);
return upsample8kTo16k(pcm16);
}
}