69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package pkg
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"l_szr_go/entity"
|
|
"os"
|
|
)
|
|
|
|
func SaveAsWav(buffer *bytes.Buffer, filename string, config entity.Config) error {
|
|
if buffer.Len() == 0 {
|
|
return fmt.Errorf("缓冲区为空,无法保存")
|
|
}
|
|
|
|
file, err := os.Create(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("创建文件失败: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
// 写入 WAV 头部
|
|
if err := writeWavHeader(file, config.SampleRate, config.BitDepth, config.Channels, buffer.Len()); err != nil {
|
|
return fmt.Errorf("写入 WAV 头部失败: %v", err)
|
|
}
|
|
|
|
// 写入 PCM 数据
|
|
if _, err := buffer.WriteTo(file); err != nil {
|
|
return fmt.Errorf("写入 PCM 数据失败: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func writeWavHeader(w io.Writer, sampleRate, bitDepth, channels, dataSize int) error {
|
|
header := struct {
|
|
ChunkID [4]byte
|
|
ChunkSize uint32
|
|
Format [4]byte
|
|
Subchunk1ID [4]byte
|
|
Subchunk1Size uint32
|
|
AudioFormat uint16
|
|
NumChannels uint16
|
|
SampleRate uint32
|
|
ByteRate uint32
|
|
BlockAlign uint16
|
|
BitsPerSample uint16
|
|
Subchunk2ID [4]byte
|
|
Subchunk2Size uint32
|
|
}{
|
|
ChunkID: [4]byte{'R', 'I', 'F', 'F'},
|
|
ChunkSize: 36 + uint32(dataSize),
|
|
Format: [4]byte{'W', 'A', 'V', 'E'},
|
|
Subchunk1ID: [4]byte{'f', 'm', 't', ' '},
|
|
Subchunk1Size: 16,
|
|
AudioFormat: 1, // PCM
|
|
NumChannels: uint16(channels),
|
|
SampleRate: uint32(sampleRate),
|
|
ByteRate: uint32(sampleRate * channels * bitDepth / 8),
|
|
BlockAlign: uint16(channels * bitDepth / 8),
|
|
BitsPerSample: uint16(bitDepth),
|
|
Subchunk2ID: [4]byte{'d', 'a', 't', 'a'},
|
|
Subchunk2Size: uint32(dataSize),
|
|
}
|
|
|
|
return binary.Write(w, binary.LittleEndian, header)
|
|
}
|