diff options
| author | jhurst <jhurst@cinecert.com> | 2006-03-14 00:29:50 +0000 |
|---|---|---|
| committer | jhurst <> | 2006-03-14 00:29:50 +0000 |
| commit | 30d642bd3b8474744dfbdcc2bdc46cdf827102c4 (patch) | |
| tree | e31c3e1456494dec612f705e957ea8f9ba7979fc /src/Wav.cpp | |
| parent | 9bfe9676115531eb76649e1ebd5e14b904b53ae2 (diff) | |
added aiff reader
Diffstat (limited to 'src/Wav.cpp')
| -rwxr-xr-x | src/Wav.cpp | 179 |
1 files changed, 170 insertions, 9 deletions
diff --git a/src/Wav.cpp b/src/Wav.cpp index 42e0d21..ce64a78 100755 --- a/src/Wav.cpp +++ b/src/Wav.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005, John Hurst +Copyright (c) 2005-2006, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,11 +29,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \brief Wave file common elements */ -#include <Wav.h> +#include "Wav.h" +#include "hex_utils.h" #include <assert.h> -const ui32_t SimpleHeaderLength = 46; +const ui32_t SimpleWavHeaderLength = 46; // ASDCP::Wav::SimpleWaveHeader::SimpleWaveHeader(ASDCP::PCM::AudioDescriptor& ADesc) @@ -71,7 +72,7 @@ ASDCP::Result_t ASDCP::Wav::SimpleWaveHeader::WriteToFile(ASDCP::FileWriter& OutFile) const { ui32_t write_count; - byte_t tmp_header[SimpleHeaderLength]; + byte_t tmp_header[SimpleWavHeaderLength]; byte_t* p = tmp_header; static ui32_t fmt_len = @@ -83,7 +84,7 @@ ASDCP::Wav::SimpleWaveHeader::WriteToFile(ASDCP::FileWriter& OutFile) const + sizeof(bitspersample) + sizeof(cbsize); - ui32_t RIFF_len = data_len + SimpleHeaderLength - 8; + ui32_t RIFF_len = data_len + SimpleWavHeaderLength - 8; memcpy(p, &FCC_RIFF, sizeof(fourcc)); p += 4; *((ui32_t*)p) = ASDCP_i32_LE(RIFF_len); p += 4; @@ -100,7 +101,7 @@ ASDCP::Wav::SimpleWaveHeader::WriteToFile(ASDCP::FileWriter& OutFile) const memcpy(p, &FCC_data, sizeof(fourcc)); p += 4; *((ui32_t*)p) = ASDCP_i32_LE(data_len); p += 4; - return OutFile.Write(tmp_header, SimpleHeaderLength, &write_count); + return OutFile.Write(tmp_header, SimpleWavHeaderLength, &write_count); } // @@ -125,7 +126,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromFile(const ASDCP::FileReader& InFile, ui32 ASDCP::Result_t ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start) { - if ( buf_len < SimpleHeaderLength ) + if ( buf_len < SimpleWavHeaderLength ) return RESULT_SMALLBUF; *data_start = 0; @@ -135,7 +136,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, fourcc test_RIFF(p); p += 4; if ( test_RIFF != FCC_RIFF ) { - DefaultLogSink().Error("Files does not begin with RIFF header\n"); + DefaultLogSink().Error("File does not begin with RIFF header\n"); return RESULT_RAW_FORMAT; } @@ -144,7 +145,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, fourcc test_WAVE(p); p += 4; if ( test_WAVE != FCC_WAVE ) { - DefaultLogSink().Error("Files does not begin with WAVE header\n"); + DefaultLogSink().Error("File does not contain a WAVE header\n"); return RESULT_RAW_FORMAT; } @@ -200,6 +201,166 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, return RESULT_OK; } +//------------------------------------------------------------------------------------------ +// conversion algorithms from http://www.borg.com/~jglatt/tech/aiff.htm + +// +void +Rat_to_extended(ASDCP::Rational rate, byte_t* buf) +{ + memset(buf, 0, 10); + ui32_t value = (ui32_t)ceil(rate.Quotient()); + ui32_t exp = value; + exp >>= 1; + ui8_t i = 0; + + for ( ; i < 32; i++ ) + { + exp >>= 1; + if ( ! exp ) + break; + } + + *(buf+1) = i; + + for ( i = 32; i != 0 ; i-- ) + { + if ( value & 0x80000000 ) + break; + value <<= 1; + } + + *(ui32_t*)(buf+2) = ASDCP_i32_BE(value); +} + +// +ASDCP::Rational +extended_to_Rat(const byte_t* buf) +{ + ui32_t last = 0; + ui32_t mantissa = ASDCP_i32_BE(*(ui32_t*)(buf+2)); + + byte_t exp = 30 - *(buf+1); + + while ( exp-- ) + { + last = mantissa; + mantissa >>= 1; + } + + if ( last & 0x00000001 ) + mantissa++; + + return ASDCP::Rational(mantissa, 1); +} + +// +void +ASDCP::AIFF::SimpleAIFFHeader::FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::Rational PictureRate) const +{ + ADesc.SampleRate = PictureRate; + + ADesc.ChannelCount = numChannels; + ADesc.AudioSamplingRate = extended_to_Rat(sampleRate); + ADesc.QuantizationBits = sampleSize; + ADesc.BlockAlign = sampleSize / 8; + ADesc.AvgBps = ADesc.BlockAlign * (ui32_t)ceil(ADesc.AudioSamplingRate.Quotient()); + ui32_t FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(ADesc); + ADesc.ContainerDuration = data_len / FrameBufferSize; +} + +// +ASDCP::Result_t +ASDCP::AIFF::SimpleAIFFHeader::ReadFromFile(const ASDCP::FileReader& InFile, ui32_t* data_start) +{ + ui32_t read_count = 0; + ui32_t local_data_start = 0; + ASDCP::PCM::FrameBuffer TmpBuffer(Wav::MaxWavHeader); + + if ( data_start == 0 ) + data_start = &local_data_start; + + Result_t result = InFile.Read(TmpBuffer.Data(), TmpBuffer.Capacity(), &read_count); + + if ( ASDCP_SUCCESS(result) ) + result = ReadFromBuffer(TmpBuffer.RoData(), read_count, data_start); + + return result; +} + +// +ASDCP::Result_t +ASDCP::AIFF::SimpleAIFFHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start) +{ + if ( buf_len < 32 ) + return RESULT_SMALLBUF; + + *data_start = 0; + const byte_t* p = buf; + const byte_t* end_p = p + buf_len; + + fourcc test_FORM(p); p += 4; + if ( test_FORM != FCC_FORM ) + { + DefaultLogSink().Error("File does not begin with FORM header\n"); + return RESULT_RAW_FORMAT; + } + + ui32_t RIFF_len = ASDCP_i32_BE(*(ui32_t*)p); p += 4; + + fourcc test_AIFF(p); p += 4; + if ( test_AIFF != FCC_AIFF ) + { + DefaultLogSink().Error("File does not contain an AIFF header\n"); + return RESULT_RAW_FORMAT; + } + + fourcc test_fcc; + + while ( p < end_p ) + { + test_fcc = fourcc(p); p += 4; + ui32_t chunk_size = ASDCP_i32_BE(*(ui32_t*)p); p += 4; + + if ( test_fcc == FCC_COMM ) + { + numChannels = ASDCP_i16_BE(*(ui16_t*)p); p += 2; + numSampleFrames = ASDCP_i32_BE(*(ui32_t*)p); p += 4; + sampleSize = ASDCP_i16_BE(*(ui16_t*)p); p += 2; + memcpy(sampleRate, p, 10); + p += 10; + } + else if ( test_fcc == FCC_SSND ) + { + if ( chunk_size > RIFF_len ) + { + DefaultLogSink().Error("Chunk size %lu larger than file: %lu\n", chunk_size, RIFF_len); + return RESULT_RAW_FORMAT; + } + + ui32_t offset = ASDCP_i32_BE(*(ui32_t*)p); p += 4; + p += 4; // blockSize; + + data_len = chunk_size - 8; + *data_start = (p - buf) + offset; + fprintf(stderr, "*data_start: %p\n", *data_start); + break; + } + else + { + p += chunk_size; + } + } + + if ( *data_start == 0 ) // can't have no data! + { + DefaultLogSink().Error("No data chunk found, file contains no essence\n"); + return RESULT_RAW_FORMAT; + } + + return RESULT_OK; +} + // |
