Added 24-bit and 8-bit modes to TTA encoder

This commit is contained in:
DataHoarder 2022-04-17 23:25:38 +02:00
parent 4623419be8
commit 5b9e39122c
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
5 changed files with 86 additions and 26 deletions

View file

@ -13,31 +13,29 @@ Collection of audio utilities for decoding/encoding files and streams.
## Codecs supported
| Codec | Containers | Decoder | Analyzer | Encoder | Notes |
|:----------:|:----------------------------------------------------------------------------------------:|:-------:|:--------:|:-------:|:------------------------------------------------------------------------------------------------------------------------------------------------------|
| **FLAC** | [FLAC](https://xiph.org/flac/format.html), [Ogg](https://xiph.org/flac/ogg_mapping.html) | ✅ | ✅ | ✅ | Adjustable encoding compression level and block size. |
| **TTA** | [TTA](https://www.tausoft.org/en/true_audio_codec_format/) | ✅ | ✅ | ✅ | Only 16bit encoding |
| **MP3** | [MP3](http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html) | ✅ | - | ✅ | Adjustable encoding bitrate and mode. Decoding via [minimp3](https://github.com/kvark128/minimp3), encoding via [LAME](https://lame.sourceforge.io/). |
| **Opus** | [Ogg](https://www.xiph.org/ogg/doc/framing.html) | ✅ | - | ✅ | Adjustable encoding bitrate. |
| **Vorbis** | [Ogg](https://www.xiph.org/ogg/doc/framing.html) | ✅ | - | ❌ | |
| **AAC** | [ADTS](https://wiki.multimedia.cx/index.php/ADTS) | ✅ | - | ✅ | Adjustable encoding bitrate and mode (LC, HEv2). |
| Codec | Containers | Decoder | Analyzer | Encoder | Notes |
|:----------:|:----------------------------------------------------------------------------------------:|:-------:|:--------:|:-------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **FLAC** | [FLAC](https://xiph.org/flac/format.html), [Ogg](https://xiph.org/flac/ogg_mapping.html) | ✅ | ✅ | ✅ | Adjustable encoding compression level and block size.<br/>Decoding/encoding by [libFLAC](https://github.com/xiph/flac) via [goflac](https://git.gammaspectra.live/S.O.N.G/goflac). |
| **TTA** | [TTA](https://www.tausoft.org/en/true_audio_codec_format/) | ✅ | ✅ | ✅ | Decoding/encoding via [go-tta](https://git.gammaspectra.live/S.O.N.G/go-tta). |
| **MP3** | [MP3](http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html) | ✅ | - | ✅ | Adjustable encoding bitrate and mode.<br/>Decoding via [minimp3](https://github.com/kvark128/minimp3), encoding by [LAME](https://lame.sourceforge.io/) via [go-lame](https://github.com/viert/go-lame). |
| **Opus** | [Ogg](https://www.xiph.org/ogg/doc/framing.html) | ✅ | - | ✅ | Adjustable encoding bitrate.<br/>Decoding/encoding by [libopus](https://github.com/xiph/opus) via [go-pus](https://git.gammaspectra.live/S.O.N.G/go-pus). |
| **Vorbis** | [Ogg](https://www.xiph.org/ogg/doc/framing.html) | ✅ | - | ❌ | Decoding by [jfreymuth/vorbis](https://github.com/jfreymuth/vorbis) via [jfreymuth/oggvorbis](https://github.com/jfreymuth/oggvorbis). |
| **AAC** | [ADTS](https://wiki.multimedia.cx/index.php/ADTS) | ✅ | - | ✅ | Adjustable encoding bitrate and mode (LC, HEv2).<br/>Decoding/encoding by [FDK-AAC](https://github.com/mstorsjo/fdk-aac) via [go-fdkaac](https://git.gammaspectra.live/S.O.N.G/go-fdkaac). |
## Container packetizers supported
| Container | Packetizer | Keep Mode | Sample Number |
|:---------:|:----------:|:---------:|:-------------:|
| **FLAC** | ✅ | ✅ | ✅ |
| **TTA** | ❌ | - | - |
| **MP3** | ✅ | ✅ | ✅ |
| **Ogg** | ✅ | ✅ | ✅* |
| **ADTS** | ✅ | ✅ | ✅ |
* *Sample number (absolute granule position) of Ogg depends on underlying codec implementing it. Has been tested as working for Opus
| Container | Packetizer | Keep Mode | Sample Numbers | Notes |
|:---------:|:----------:|:---------:|:--------------:|:---------------------------------------------------------------------------------------------------------------------------------------|
| **FLAC** | ✅ | ✅ | ✅ | Uses [mewkiz/flac](https://github.com/mewkiz/flac) for parsing streams. |
| **TTA** | ❌ | - | - | |
| **MP3** | ✅ | ✅ | ✅ | Uses [sssgun/mp3](https://github.com/sssgun/mp3) as a frame parser. |
| **Ogg** | ✅ | ✅ | ✅* | *Sample numbers (absolute granule position in Ogg) depend on underlying codec implementing it.<br/>Has been tested as working for Opus |
| **ADTS** | ✅ | ✅ | ✅ | Uses [edgeware/mp4ff](https://github.com/edgeware/mp4ff) for its ADTS frame parser. |
## Dependencies
### Go >= 1.18
### [libFLAC](https://github.com/xiph/flac) (required by [goflac](https://github.com/cocoonlife/goflac))
### [libFLAC](https://github.com/xiph/flac) (required by [goflac](https://git.gammaspectra.live/S.O.N.G/goflac))
```shell
sudo apt install libflac-dev
```

View file

@ -171,10 +171,6 @@ func (f Format) Encode(source audio.Source, writer io.WriteCloser, options map[s
}
}
if bitsPerSample != 16 { //TODO
return errors.New("not supported bits")
}
var encoder *libtta.Encoder
if writeSeeker, ok := writer.(io.ReadWriteSeeker); ok {
@ -201,11 +197,31 @@ func (f Format) Encode(source audio.Source, writer io.WriteCloser, options map[s
return err
}
for block := range source.Blocks {
switch bitsPerSample {
case 24:
for block := range source.Blocks {
samples := cgo.Float32ToInt16(block)
samples := cgo.Float32ToInt24(block)
encoder.ProcessStream(unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)), nil)
}
case 16:
for block := range source.Blocks {
samples := cgo.Float32ToInt16(block)
encoder.ProcessStream(unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)*2), nil)
}
case 8:
for block := range source.Blocks {
samples := cgo.Float32ToInt8(block)
encoder.ProcessStream(unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)), nil)
}
default:
return errors.New("not supported bits per sample")
encoder.ProcessStream(unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)*2), nil)
}
encoder.Finalize()

View file

@ -184,6 +184,23 @@ void audio_float32_to_int32(float* restrict data, size_t data_len, int32_t* rest
}
}
void audio_float32_to_int24(float* restrict data, size_t data_len, int8_t* restrict buffer){
for (int i = 0; i < data_len; ++i){
float f = data[i];
if (f < -1.0) {
f = -1.0;
}
if (f > 1.0) {
f = 1.0;
}
int32_t value = (int32_t)(f * BITS_TO_DIV(24));
buffer[i*3] = (int8_t) (value & 0xFF);
buffer[i*3+1] = (int8_t) ((value >> 8) & 0xFF);
buffer[i*3+2] = (int8_t) ((value >> 16) & 0xFF);
}
}
void audio_float32_to_int16(float* restrict data, size_t data_len, int16_t* restrict buffer){
for (int i = 0; i < data_len; ++i){
float f = data[i];
@ -195,4 +212,17 @@ void audio_float32_to_int16(float* restrict data, size_t data_len, int16_t* rest
}
buffer[i] = (int16_t)(f * BITS_TO_DIV(16));
}
}
void audio_float32_to_int8(float* restrict data, size_t data_len, int8_t* restrict buffer){
for (int i = 0; i < data_len; ++i){
float f = data[i];
if (f < -1.0) {
f = -1.0;
}
if (f > 1.0) {
f = 1.0;
}
buffer[i] = (int8_t)(f * BITS_TO_DIV(8));
}
}

View file

@ -57,8 +57,20 @@ func Float32ToInt32(data []float32, bitDepth int) (buf []int32) {
return
}
func Float32ToInt24(data []float32) (buf []byte) {
buf = make([]byte, len(data)*3)
C.audio_float32_to_int24((*C.float)(&data[0]), C.size_t(len(data)), (*C.int8_t)(unsafe.Pointer(&buf[0])))
return
}
func Float32ToInt16(data []float32) (buf []int16) {
buf = make([]int16, len(data))
C.audio_float32_to_int16((*C.float)(&data[0]), C.size_t(len(data)), (*C.int16_t)(&buf[0]))
return
}
func Float32ToInt8(data []float32) (buf []int8) {
buf = make([]int8, len(data))
C.audio_float32_to_int8((*C.float)(&data[0]), C.size_t(len(data)), (*C.int8_t)(&buf[0]))
return
}

View file

@ -21,4 +21,8 @@ void audio_int8_to_float32(int8_t* restrict data, size_t data_len, float* restri
void audio_float32_to_int32(float* restrict data, size_t data_len, int32_t* restrict buffer, int bitDepth);
void audio_float32_to_int16(float* restrict data, size_t data_len, int16_t* restrict buffer);
void audio_float32_to_int24(float* restrict data, size_t data_len, int8_t* restrict buffer);
void audio_float32_to_int16(float* restrict data, size_t data_len, int16_t* restrict buffer);
void audio_float32_to_int8(float* restrict data, size_t data_len, int8_t* restrict buffer);