feat: added record qso dvk
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
//go:build windows
|
||||
|
||||
package audio
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/braheezy/shine-mp3/pkg/mp3"
|
||||
)
|
||||
|
||||
// mp3Rate is the encode sample rate. The capture pipeline is 16 kHz, but the
|
||||
// Shine encoder emits broken "free-format" frames at MPEG-2 rates (16/22/24
|
||||
// kHz) that most players reject. Encoding at an MPEG-1 rate (we upsample ×2 to
|
||||
// 32 kHz) produces standard, universally-playable MP3s.
|
||||
const mp3Rate = sampleRate * 2 // 32000
|
||||
|
||||
// writeMP3 encodes 16 kHz mono 16-bit PCM to a standard MP3 file using the
|
||||
// pure-Go Shine encoder (no CGO). Two quirks are worked around:
|
||||
// - 16 kHz (MPEG-2) yields broken free-format frames → upsample ×2 to 32 kHz.
|
||||
// - Shine's Write only encodes half the samples for MONO input (its loop
|
||||
// advances by samples_per_pass*2). Feeding STEREO interleaved data (the
|
||||
// encoder reads samples_per_pass*channels per pass) encodes everything, so
|
||||
// we duplicate mono → L=R stereo.
|
||||
func writeMP3(path string, pcm []byte) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
mono32 := upsample2(bytesToInt16(pcm)) // 16 kHz → 32 kHz mono
|
||||
stereo := make([]int16, len(mono32)*2) // L=R interleaved
|
||||
for i, v := range mono32 {
|
||||
stereo[2*i], stereo[2*i+1] = v, v
|
||||
}
|
||||
enc := mp3.NewEncoder(mp3Rate, 2)
|
||||
return enc.Write(f, stereo)
|
||||
}
|
||||
|
||||
// upsample2 doubles the sample rate with linear interpolation (16 kHz → 32 kHz).
|
||||
func upsample2(in []int16) []int16 {
|
||||
if len(in) == 0 {
|
||||
return in
|
||||
}
|
||||
out := make([]int16, len(in)*2)
|
||||
for i := range in {
|
||||
out[2*i] = in[i]
|
||||
if i+1 < len(in) {
|
||||
out[2*i+1] = int16((int32(in[i]) + int32(in[i+1])) / 2)
|
||||
} else {
|
||||
out[2*i+1] = in[i]
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user