async generateAFSKWav(bitstream: string, baud, mark, space): Promise<Blob> {
const sampleRate = 16000; // Sample rate in Hz
const fadeDuration = 50; // Number of samples for smooth frequency transition
const samplesPerBit = Math.round(sampleRate / baud);
const totalSamples = bitstream.length * samplesPerBit;
let audioSamples: Float32Array = new Float32Array(totalSamples);
let phase = 0.0;
let currentFreq = bitstream[0] === "1" ? mark : space;
let currentPhaseIncrement = (2 * Math.PI * currentFreq) / sampleRate;
for (let bitIndex = 0; bitIndex < bitstream.length; bitIndex++) {
const newFreq = bitstream[bitIndex] === "1" ? mark : space;
const newPhaseIncrement = (2 * Math.PI * newFreq) / sampleRate;
for (let i = 0; i < samplesPerBit; i++) {
if (i < fadeDuration) {
// Smooth frequency transition (interpolation)
const fadeFactor = i / fadeDuration;
const interpolatedFreq = currentFreq * (1 - fadeFactor) + newFreq * fadeFactor;
currentPhaseIncrement = (2 * Math.PI * interpolatedFreq) / sampleRate;
} else {
currentPhaseIncrement = newPhaseIncrement;
}
// Generate waveform sample
audioSamples[bitIndex * samplesPerBit + i] = Math.sin(phase);
phase += currentPhaseIncrement;
if (phase >= 2 * Math.PI) {
phase -= 2 * Math.PI;
}
}
currentFreq = newFreq;
}
// Convert to WAV format
const wavBuffer = await WavEncoder.encode({
sampleRate: sampleRate,
channelData: [audioSamples] // Mono channel
});