diff --git a/README.md b/README.md index ec4d002..56012a3 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/codec/Makefile.am b/codec/Makefile.am index b5ce828..999cba9 100644 --- a/codec/Makefile.am +++ b/codec/Makefile.am @@ -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 diff --git a/codec/libalac.cpp b/codec/libalac.cpp new file mode 100644 index 0000000..6d54c37 --- /dev/null +++ b/codec/libalac.cpp @@ -0,0 +1,134 @@ +#include +#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(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(encoder->ptr); + + AudioFormatDescription outputFormat; + outputFormat.mFormatID = kALACFormatAppleLossless; + outputFormat.mSampleRate = static_cast(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(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(input), output, &ioNumBytes) != ALAC_noErr){ + return -1; + } + + return ioNumBytes; + +} +void alac_encoder_delete(alac_encoder* encoder){ + delete reinterpret_cast(encoder->ptr); + encoder->ptr = nullptr; +} diff --git a/codec/libalac.h b/codec/libalac.h new file mode 100644 index 0000000..5be2c32 --- /dev/null +++ b/codec/libalac.h @@ -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 \ No newline at end of file