123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #include "AudioCoderFlac.h"
- #include <bfc/platform/types.h>
- #include <FLAC/metadata.h>
- 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;i<numSamples;i++)
- {
- buffer[i] = (FLAC__int32)in[i];
- }
- }
- static void Copy16(FLAC__int32 *buffer, void *inputData, int numSamples)
- {
- int16_t *in = (int16_t *)inputData;
- for (int i=0;i<numSamples;i++)
- {
- buffer[i] = (FLAC__int32)in[i];
- }
- }
- static void Copy24(FLAC__int32 *buffer, void *inputData, int numSamples)
- {
- uint8_t *in = (uint8_t *)inputData;
- for (int i=0;i<numSamples;i++)
- {
- FLAC__int32 val = (((FLAC__int32)in[0]) << 0);
- val = val | (((FLAC__int32)in[1]) << 8);
- val = val | (((FLAC__int32)in[2]) << 16);
- buffer[i] = (FLAC__int32)val;
- in+=3;
- }
- }
- static void Copy32(FLAC__int32 *buffer, void *inputData, int numSamples)
- {
- int32_t *in = (int32_t *)inputData;
- for (int i=0;i<numSamples;i++)
- {
- buffer[i] = (FLAC__int32)in[i];
- }
- }
- int AudioCoderFlac::Encode(int framepos, void *in, int in_avail, int *in_used, void *out, int out_avail)
- {
- FLAC__int32 buffer[65536];
- FLAC__uint64 startBytes = win32State.bytesWritten;
- if (!in_avail)
- {
- if (finished)
- {
- int ret = (int)finishedBytes;
- finishedBytes = 0;
- return ret;
- }
- return 0;
- }
- int numSamples = in_avail/(bps/8);
- if (numSamples>65536)
- 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);
- }
- }
|