vosk-recognize-dev/pkg/wav/list_chunk.go
2025-10-23 13:06:22 +07:00

178 lines
5.7 KiB
Go

package wav
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"rtp-app/pkg/riff"
)
var (
markerIART = [4]byte{'I', 'A', 'R', 'T'}
markerISFT = [4]byte{'I', 'S', 'F', 'T'}
markerICRD = [4]byte{'I', 'C', 'R', 'D'}
markerICOP = [4]byte{'I', 'C', 'O', 'P'}
markerIARL = [4]byte{'I', 'A', 'R', 'L'}
markerINAM = [4]byte{'I', 'N', 'A', 'M'}
markerIENG = [4]byte{'I', 'E', 'N', 'G'}
markerIGNR = [4]byte{'I', 'G', 'N', 'R'}
markerIPRD = [4]byte{'I', 'P', 'R', 'D'}
markerISRC = [4]byte{'I', 'S', 'R', 'C'}
markerISBJ = [4]byte{'I', 'S', 'B', 'J'}
markerICMT = [4]byte{'I', 'C', 'M', 'T'}
markerITRK = [4]byte{'I', 'T', 'R', 'K'}
markerITRKBug = [4]byte{'i', 't', 'r', 'k'}
markerITCH = [4]byte{'I', 'T', 'C', 'H'}
markerIKEY = [4]byte{'I', 'K', 'E', 'Y'}
markerIMED = [4]byte{'I', 'M', 'E', 'D'}
)
func DecodeListChunk(d *Decoder, ch *riff.Chunk) error {
if ch == nil {
return fmt.Errorf("can't decode a nil chunk")
}
if d == nil {
return fmt.Errorf("nil decoder")
}
if ch.ID == CIDList {
buf := make([]byte, ch.Size)
var err error
if _, err = ch.Read(buf); err != nil {
return fmt.Errorf("failed to read the LIST chunk - %v", err)
}
r := bytes.NewReader(buf)
scratch := make([]byte, 4)
if _, err = r.Read(scratch); err != nil {
return fmt.Errorf("failed to read the INFO subchunk - %v", err)
}
if !bytes.Equal(scratch, CIDInfo[:]) {
ch.Drain()
return nil
}
if d.Metadata == nil {
d.Metadata = &Metadata{}
}
var (
id [4]byte
size uint32
)
readSubHeader := func() error {
if err := binary.Read(r, binary.BigEndian, &id); err != nil {
return err
}
return binary.Read(r, binary.LittleEndian, &size)
}
for err == nil {
err = readSubHeader()
if err != nil {
break
}
scratch = make([]byte, size)
r.Read(scratch)
switch id {
case markerIARL:
d.Metadata.Location = nullTermStr(scratch)
case markerIART:
d.Metadata.Artist = nullTermStr(scratch)
case markerISFT:
d.Metadata.Software = nullTermStr(scratch)
case markerICRD:
d.Metadata.CreationDate = nullTermStr(scratch)
case markerICOP:
d.Metadata.Copyright = nullTermStr(scratch)
case markerINAM:
d.Metadata.Title = nullTermStr(scratch)
case markerIENG:
d.Metadata.Engineer = nullTermStr(scratch)
case markerIGNR:
d.Metadata.Genre = nullTermStr(scratch)
case markerIPRD:
d.Metadata.Product = nullTermStr(scratch)
case markerISRC:
d.Metadata.Source = nullTermStr(scratch)
case markerISBJ:
d.Metadata.Subject = nullTermStr(scratch)
case markerICMT:
d.Metadata.Comments = nullTermStr(scratch)
case markerITRK, markerITRKBug:
d.Metadata.TrackNbr = nullTermStr(scratch)
case markerITCH:
d.Metadata.Technician = nullTermStr(scratch)
case markerIKEY:
d.Metadata.Keywords = nullTermStr(scratch)
case markerIMED:
d.Metadata.Medium = nullTermStr(scratch)
}
if size%2 == 1 {
r.Seek(1, io.SeekCurrent)
}
}
}
ch.Drain()
return nil
}
func encodeInfoChunk(e *Encoder) []byte {
if e == nil || e.Metadata == nil {
return nil
}
buf := bytes.NewBuffer(nil)
writeSection := func(id [4]byte, val string) {
buf.Write(id[:])
binary.Write(buf, binary.LittleEndian, uint32(len(val)+1))
buf.Write(append([]byte(val), 0x00))
}
if e.Metadata.Artist != "" {
writeSection(markerIART, e.Metadata.Artist)
}
if e.Metadata.Comments != "" {
writeSection(markerICMT, e.Metadata.Comments)
}
if e.Metadata.Copyright != "" {
writeSection(markerICOP, e.Metadata.Copyright)
}
if e.Metadata.CreationDate != "" {
writeSection(markerICRD, e.Metadata.CreationDate)
}
if e.Metadata.Engineer != "" {
writeSection(markerIENG, e.Metadata.Engineer)
}
if e.Metadata.Technician != "" {
writeSection(markerITCH, e.Metadata.Technician)
}
if e.Metadata.Genre != "" {
writeSection(markerIGNR, e.Metadata.Genre)
}
if e.Metadata.Keywords != "" {
writeSection(markerIKEY, e.Metadata.Keywords)
}
if e.Metadata.Medium != "" {
writeSection(markerIMED, e.Metadata.Medium)
}
if e.Metadata.Title != "" {
writeSection(markerINAM, e.Metadata.Title)
}
if e.Metadata.Product != "" {
writeSection(markerIPRD, e.Metadata.Product)
}
if e.Metadata.Subject != "" {
writeSection(markerISBJ, e.Metadata.Subject)
}
if e.Metadata.Software != "" {
writeSection(markerISFT, e.Metadata.Software)
}
if e.Metadata.Source != "" {
writeSection(markerISRC, e.Metadata.Source)
}
if e.Metadata.Location != "" {
writeSection(markerIARL, e.Metadata.Location)
}
if e.Metadata.TrackNbr != "" {
writeSection(markerITRK, e.Metadata.TrackNbr)
}
return append(CIDInfo, buf.Bytes()...)
}