mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
0f395ce110
* refactor: update ASR and TTS implementations * fix lint * Integrating asr/tts models w/ new security config * update documents * add arbitrary whisper transcriptor support * update documents * fix lint * add mimo tts
58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package audio
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// DecodeOggOpus reads an Ogg format stream and extracts individual Opus payloads.
|
|
// It calls onFrame for every complete Opus frame found in the stream.
|
|
func DecodeOggOpus(r io.Reader, onFrame func([]byte) error) error {
|
|
var packet bytes.Buffer
|
|
header := make([]byte, 27)
|
|
segment := make([]byte, 255)
|
|
|
|
for {
|
|
if _, err := io.ReadFull(r, header); err != nil {
|
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("failed to read ogg header: %w", err)
|
|
}
|
|
if string(header[:4]) != "OggS" {
|
|
return fmt.Errorf("invalid ogg magic string")
|
|
}
|
|
|
|
pageSegments := int(header[26])
|
|
segmentTable := make([]byte, pageSegments)
|
|
if _, err := io.ReadFull(r, segmentTable); err != nil {
|
|
return fmt.Errorf("failed to read segment table: %w", err)
|
|
}
|
|
|
|
for _, lacing := range segmentTable {
|
|
if _, err := io.ReadFull(r, segment[:lacing]); err != nil {
|
|
return fmt.Errorf("failed to read segment data: %w", err)
|
|
}
|
|
|
|
packet.Write(segment[:lacing])
|
|
|
|
// If lacing is less than 255, the packet is complete
|
|
if lacing < 255 {
|
|
if packet.Len() > 0 {
|
|
packetBytes := packet.Bytes()
|
|
// Ignore Ogg Opus headers
|
|
if !bytes.HasPrefix(packetBytes, []byte("OpusHead")) &&
|
|
!bytes.HasPrefix(packetBytes, []byte("OpusTags")) {
|
|
if err := onFrame(packetBytes); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Start new packet
|
|
packet.Reset()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|