1
0
forked from um/cli

Add Tm Decoder

Update XM Decoder
This commit is contained in:
Emmm Monster 2020-12-26 04:54:59 +08:00
parent 0eb8ade0e9
commit 7c0d6604a2
No known key found for this signature in database
GPG Key ID: C98279C83FB50DB9
2 changed files with 68 additions and 25 deletions

47
algo/tm/xm.go Normal file
View File

@ -0,0 +1,47 @@
package tm
import (
"bytes"
"errors"
"github.com/umlock-music/cli/algo/common"
)
var magicHeader = []byte{0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}
type Decoder struct {
file []byte
}
func (d *Decoder) GetCoverImage() []byte {
return nil
}
func (d *Decoder) GetAudioData() []byte {
return d.file[8:]
}
func (d *Decoder) GetAudioExt() string {
return ""
}
func (d *Decoder) GetMeta() common.Meta {
return nil
}
func NewDecoder(data []byte) *Decoder {
return &Decoder{file: data}
}
func (d *Decoder) Validate() error {
if len(d.file) < 8 {
return errors.New("invalid file size")
}
if !bytes.Equal(magicHeader, d.file[:8]) {
return errors.New("not a valid tm file")
}
return nil
}
func (d *Decoder) Decode() error {
return nil
}

View File

@ -9,24 +9,20 @@ import (
) )
var ( var (
xmMagicHeader = []byte{'i', 'f', 'm', 't'} magicHeader = []byte{'i', 'f', 'm', 't'}
xmMagicHeader2 = []byte{0xfe, 0xfe, 0xfe, 0xfe} magicHeader2 = []byte{0xfe, 0xfe, 0xfe, 0xfe}
xmHeaders map[string]string typeMapping = map[string]string{
ErrXmFileSize = errors.New("xm invalid file size")
ErrXmMagicHeader = errors.New("xm magic header not matched")
)
func init() {
xmHeaders = map[string]string{
" WAV": "wav", " WAV": "wav",
"FLAC": "flac", "FLAC": "flac",
" MP3": "mp3", " MP3": "mp3",
" A4M": "m4a", " A4M": "m4a",
} }
} ErrFileSize = errors.New("xm invalid file size")
ErrMagicHeader = errors.New("xm magic header not matched")
)
type Decoder struct { type Decoder struct {
data []byte file []byte
headerLen uint32 headerLen uint32
outputExt string outputExt string
mask byte mask byte
@ -50,38 +46,38 @@ func (d *Decoder) GetMeta() common.Meta {
} }
func NewDecoder(data []byte) *Decoder { func NewDecoder(data []byte) *Decoder {
return &Decoder{data: data} return &Decoder{file: data}
} }
func (d *Decoder) Validate() error { func (d *Decoder) Validate() error {
lenData := len(d.data) lenData := len(d.file)
if lenData < 16 { if lenData < 16 {
return ErrXmFileSize return ErrFileSize
} }
if !bytes.Equal(xmMagicHeader, d.data[:4]) || if !bytes.Equal(magicHeader, d.file[:4]) ||
!bytes.Equal(xmMagicHeader2, d.data[8:12]) { !bytes.Equal(magicHeader2, d.file[8:12]) {
return ErrXmMagicHeader return ErrMagicHeader
} }
var ok bool var ok bool
d.outputExt, ok = xmHeaders[string(d.data[4:8])] d.outputExt, ok = typeMapping[string(d.file[4:8])]
if !ok { if !ok {
return errors.New("detect unknown xm file type: " + string(d.data[4:8])) return errors.New("detect unknown xm file type: " + string(d.file[4:8]))
} }
if d.data[14] != 0 { if d.file[14] != 0 {
logging.Log().Warn("not a simple xm file", zap.Uint8("b[14]", d.data[14])) logging.Log().Warn("not a simple xm file", zap.Uint8("b[14]", d.file[14]))
} }
d.headerLen = uint32(d.data[12]) | uint32(d.data[13])<<8 | uint32(d.data[14])<<16 // LittleEndian Unit24 d.headerLen = uint32(d.file[12]) | uint32(d.file[13])<<8 | uint32(d.file[14])<<16 // LittleEndian Unit24
if d.headerLen+16 > uint32(lenData) { if d.headerLen+16 > uint32(lenData) {
return ErrXmFileSize return ErrFileSize
} }
return nil return nil
} }
func (d *Decoder) Decode() error { func (d *Decoder) Decode() error {
d.mask = d.data[15] d.mask = d.file[15]
d.audio = d.data[16:] d.audio = d.file[16:]
dataLen := uint32(len(d.audio)) dataLen := uint32(len(d.audio))
for i := d.headerLen; i < dataLen; i++ { for i := d.headerLen; i < dataLen; i++ {
d.audio[i] = ^(d.audio[i] - d.mask) d.audio[i] = ^(d.audio[i] - d.mask)