From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp | 203 ++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp (limited to 'Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp') diff --git a/Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp b/Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp new file mode 100644 index 00000000..38bb124e --- /dev/null +++ b/Src/Plugins/Encoder/enc_flac/AudioCoderFlac.cpp @@ -0,0 +1,203 @@ +#include "AudioCoderFlac.h" +#include +#include + +AudioCoderFlac::AudioCoderFlac(unsigned int nch, unsigned int bps, unsigned int samplerate, unsigned int compression) +{ + /* initialize stuff first so we can clean up safely if things go wrong */ + finished = false; + finishedBytes = 0; + padding = 0; + encoder = 0; + win32State.bytesWritten = 0; + win32State.handle = INVALID_HANDLE_VALUE; + tempFile[0]=0; + + wchar_t tempPath[MAX_PATH-14] = {0}; + GetTempPath(MAX_PATH-14, tempPath); + GetTempFileName(tempPath, L"wfl", 0, tempFile); + win32State.handle = CreateFile(tempFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + + if (win32State.handle != INVALID_HANDLE_VALUE) + { + this->nch = nch; + this->bps = bps; + encoder = FLAC__stream_encoder_new(); + + if (!encoder) + return; + + // set stream info + if (!FLAC__stream_encoder_set_channels(encoder, nch) + || !FLAC__stream_encoder_set_bits_per_sample(encoder, bps) + || !FLAC__stream_encoder_set_sample_rate(encoder, samplerate) + || !FLAC__stream_encoder_set_total_samples_estimate(encoder, 0) + || !FLAC__stream_encoder_set_compression_level(encoder, compression) + || !FLAC__stream_encoder_set_blocksize(encoder, 0)) + { + FLAC__stream_encoder_delete(encoder); + encoder=0; + return; + } + // TODO: set any more config stuff + + // TODO: seektable? + //FLAC__StreamMetadata *seektable = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); + + padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); + if (padding) + { + padding->length = 16384; // TODO: configurable padding size + if (!FLAC__stream_encoder_set_metadata(encoder, &padding, 1)) + { + FLAC__stream_encoder_delete(encoder); + encoder=0; + return; + } + } + + if (FLAC__stream_encoder_init_stream(encoder, Win32_Write, Win32_Seek, Win32_Tell, NULL, &win32State) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) + { + FLAC__stream_encoder_delete(encoder); + encoder=0; + return; + } + } +} + +bool AudioCoderFlac::OK() +{ + if (!encoder) + return false; + + return FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK; +} + +AudioCoderFlac::~AudioCoderFlac() +{ + if (encoder) + FLAC__stream_encoder_delete(encoder); + + if (padding) + FLAC__metadata_object_delete(padding); + + if (win32State.handle != INVALID_HANDLE_VALUE) + CloseHandle(win32State.handle); + +} + +static void Copy8(FLAC__int32 *buffer, void *inputData, int numSamples) +{ + uint8_t *in = (uint8_t *)inputData; + + for (int i=0;i65536) + numSamples = 65536; + + switch (bps) + { + case 8: + Copy8(buffer, in, numSamples); + break; + case 16: + Copy16(buffer, in, numSamples); + break; + case 24: + Copy24(buffer, in, numSamples); + break; + case 32: + Copy32(buffer, in, numSamples); + break; + } + + FLAC__bool result = FLAC__stream_encoder_process_interleaved(encoder, buffer, numSamples/nch); + + if (result) + { + *in_used = numSamples*(bps/8); + return (int)(win32State.bytesWritten - startBytes); + } + + return 0; +} + +void AudioCoderFlac::PrepareToFinish() +{ + FLAC__uint64 startBytes = win32State.bytesWritten; + FLAC__stream_encoder_finish(encoder); + finishedBytes = win32State.bytesWritten - startBytes; +} + +void AudioCoderFlac::Finish(const wchar_t *destination) +{ + if (win32State.handle != INVALID_HANDLE_VALUE) + CloseHandle(win32State.handle); + + win32State.handle = INVALID_HANDLE_VALUE; + if (!MoveFile(tempFile, destination)) + { + if (CopyFile(tempFile, destination, FALSE)) + DeleteFile(tempFile); + } +} \ No newline at end of file -- cgit