Add C libalac interface for encoder

This commit is contained in:
DataHoarder 2022-04-20 20:18:57 +02:00
parent 5d6d836ee5
commit abddc2592b
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 158 additions and 2 deletions

View file

@ -21,7 +21,7 @@ To download, build and install `libalac` do the following:
* Clone the repository and `cd` into the folder:
```
$ git clone https://github.com/mikebrady/alac.git
$ git clone https://git.gammaspectra.live/S.O.N.G/alac.git
$ cd alac
```
* Configure the build and make the library:

View file

@ -27,7 +27,8 @@ libalac_la_SOURCES = \
dp_dec.c \
dp_enc.c \
matrix_dec.c \
matrix_enc.c
matrix_enc.c \
libalac.cpp
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = alac.pc

134
codec/libalac.cpp Normal file
View file

@ -0,0 +1,134 @@
#include <vector>
#include "libalac.h"
#include "ALACEncoder.h"
#include "ALACBitUtilities.h"
enum
{
kTestFormatFlag_16BitSourceData = 1,
kTestFormatFlag_20BitSourceData = 2,
kTestFormatFlag_24BitSourceData = 3,
kTestFormatFlag_32BitSourceData = 4
};
alac_encoder alac_encoder_new(int sampleRate, int channels, int bitDepth, int fastMode) {
alac_encoder encoder;
encoder.ptr = nullptr;
encoder.sample_rate = sampleRate;
encoder.channels = channels;
encoder.bit_depth = bitDepth;
encoder.input_packet_size = 0;
encoder.output_max_packet_size = 0;
AudioFormatDescription d;
d.mFormatID = kALACFormatAppleLossless;
d.mSampleRate = static_cast<alac_float64_t>(sampleRate);
switch (bitDepth) {
//TODO: hmm, source bit data?
case 16:
d.mFormatFlags = kTestFormatFlag_16BitSourceData;
break;
case 20:
d.mFormatFlags = kTestFormatFlag_20BitSourceData;
break;
case 24:
d.mFormatFlags = kTestFormatFlag_24BitSourceData;
break;
case 32:
d.mFormatFlags = kTestFormatFlag_32BitSourceData;
break;
default:
return encoder;
}
if (channels > kALACMaxChannels) {
return encoder;
}
d.mFramesPerPacket = kALACDefaultFramesPerPacket;
d.mChannelsPerFrame = channels;
d.mBytesPerPacket = 0;
d.mBytesPerFrame = 0;
d.mBitsPerChannel = 0;
d.mReserved = 0;
auto e = new ALACEncoder();
e->SetFrameSize(d.mFramesPerPacket);
e->SetFastMode(fastMode != 0);
if(e->InitializeEncoder(d) != ALAC_noErr){
delete e;
return encoder;
}
encoder.ptr = e;
encoder.input_packet_size = channels * (bitDepth >> 3) * d.mFramesPerPacket;
encoder.output_max_packet_size = encoder.input_packet_size + kALACMaxEscapeHeaderBytes;
return encoder;
}
int alac_encoder_write(alac_encoder* encoder, const unsigned char * input, int input_size, unsigned char * output){
if(encoder->ptr == nullptr){
return -1;
}
auto e = reinterpret_cast<ALACEncoder*>(encoder->ptr);
AudioFormatDescription outputFormat;
outputFormat.mFormatID = kALACFormatAppleLossless;
outputFormat.mSampleRate = static_cast<alac_float64_t>(encoder->sample_rate);
outputFormat.mFramesPerPacket = kALACDefaultFramesPerPacket;
outputFormat.mChannelsPerFrame = encoder->channels;
outputFormat.mBytesPerPacket = 0;
outputFormat.mBytesPerFrame = 0;
outputFormat.mBitsPerChannel = 0;
outputFormat.mReserved = 0;
AudioFormatDescription inputFormat;
inputFormat.mFormatID = kALACFormatLinearPCM;
inputFormat.mSampleRate = static_cast<alac_float64_t>(encoder->sample_rate);
inputFormat.mFramesPerPacket = outputFormat.mFramesPerPacket;
inputFormat.mChannelsPerFrame = encoder->channels;
inputFormat.mBitsPerChannel = encoder->bit_depth;
inputFormat.mBytesPerPacket = inputFormat.mBytesPerFrame = inputFormat.mFramesPerPacket * (inputFormat.mBitsPerChannel >> 3) * inputFormat.mChannelsPerFrame;
inputFormat.mFormatFlags = kALACFormatFlagIsSignedInteger | kALACFormatFlagIsPacked; //little endian
inputFormat.mReserved = 0;
switch (encoder->bit_depth) {
//TODO: hmm, source bit data?
case 16:
outputFormat.mFormatFlags = kTestFormatFlag_16BitSourceData;
break;
case 20:
outputFormat.mFormatFlags = kTestFormatFlag_20BitSourceData;
break;
case 24:
outputFormat.mFormatFlags = kTestFormatFlag_24BitSourceData;
break;
case 32:
outputFormat.mFormatFlags = kTestFormatFlag_32BitSourceData;
break;
}
int32_t ioNumBytes = 0;
if(input_size > inputFormat.mBytesPerPacket){
return -1;
}
ioNumBytes = input_size;
if(e->Encode(inputFormat, outputFormat, const_cast<unsigned char *>(input), output, &ioNumBytes) != ALAC_noErr){
return -1;
}
return ioNumBytes;
}
void alac_encoder_delete(alac_encoder* encoder){
delete reinterpret_cast<ALACEncoder*>(encoder->ptr);
encoder->ptr = nullptr;
}

21
codec/libalac.h Normal file
View file

@ -0,0 +1,21 @@
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
void *ptr;
int sample_rate;
int channels;
int bit_depth;
int input_packet_size;
int output_max_packet_size;
} alac_encoder;
alac_encoder alac_encoder_new(int sampleRate, int channels, int bitDepth, int fastMode);
int alac_encoder_write(alac_encoder* encoder, const unsigned char * input, int input_size, unsigned char * output);
void alac_encoder_delete(alac_encoder* encoder);
#ifdef __cplusplus
}
#endif