Added 24-bit and 8-bit modes to TTA encoder
This commit is contained in:
parent
4623419be8
commit
5b9e39122c
34
README.md
34
README.md
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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()
|
||||
|
|
30
cgo/audio.c
30
cgo/audio.c
|
@ -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));
|
||||
}
|
||||
}
|
12
cgo/audio.go
12
cgo/audio.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
Loading…
Reference in a new issue