adding a reader for the AIFF and AIFF-C formats
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5742 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
SubDir OBOS_TOP src add-ons media plugins ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons media plugins aiff_reader ;
|
||||
SubInclude OBOS_TOP src add-ons media plugins au_reader ;
|
||||
SubInclude OBOS_TOP src add-ons media plugins avi_reader ;
|
||||
SubInclude OBOS_TOP src add-ons media plugins mp3_reader ;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef _AIFF_H
|
||||
#define _AIFF_H
|
||||
|
||||
// The complete size of a chunk is chunk_size + sizeof(chunk_struct)
|
||||
// If the complete size of a chunk is not even, the chunk is padded with one byte
|
||||
// sample order for multi channel sound:
|
||||
// 2: left, right
|
||||
// 3: left, right, center
|
||||
// 4: front left, front right, rear left, rear right
|
||||
// 4: left, center, right, surround
|
||||
// 6: left center, left, center, right center, right, surround
|
||||
|
||||
// Apple maps Microsoft ACM formats into a compression code of the form "ms??",
|
||||
// where the second two characters are the Microsoft Audio Compression Manager
|
||||
// (ACM) code. For instance, Microsoft ADPCM, with ACM value of 1, is mapped
|
||||
// to the code "ms\x00\x01".
|
||||
|
||||
struct chunk_struct
|
||||
{
|
||||
uint32 chunk_id;
|
||||
uint32 chunk_size;
|
||||
} _PACKED;
|
||||
|
||||
struct aiff_chunk
|
||||
{
|
||||
uint32 chunk_id; // 'FORM'
|
||||
uint32 chunk_size;
|
||||
uint32 aiff_id; // 'AIFF' or 'AIFC'
|
||||
// chunks[]
|
||||
} _PACKED;
|
||||
|
||||
struct comm_chunk
|
||||
{
|
||||
// uint32 chunk_id; // 'COMM'
|
||||
// uint32 chunk_size;
|
||||
uint16 channel_count;
|
||||
uint32 frame_count;
|
||||
uint16 bits_per_sample; // store as 8 bit entities
|
||||
char sample_rate[10]; // 80 bit IEEE floating point, big endian
|
||||
uint32 compression_id; // only present if chunk_size >= 22
|
||||
} _PACKED;
|
||||
|
||||
struct ssnd_chunk
|
||||
{
|
||||
// uint32 chunk_id; // 'SSND'
|
||||
// uint32 chunk_size;
|
||||
uint32 offset;
|
||||
uint32 block_size;
|
||||
// samples[]
|
||||
} _PACKED;
|
||||
|
||||
#if DEBUG
|
||||
inline const char * string_for_compression(uint32 compression)
|
||||
{
|
||||
static char s[64];
|
||||
switch (compression) {
|
||||
case 'NONE': return "not compressed";
|
||||
case 'ADP4': return "4:1 Intel/DVI ADPCM";
|
||||
case 'DWVW': return "Delta With Variable Word Width";
|
||||
case 'FL32': return "IEEE 32-bit floating point";
|
||||
case 'fl32': return "IEEE 32-bit floating point";
|
||||
case 'fl64': return "IEEE 64-bit floating point";
|
||||
case 'alaw': return "8-bit ITU-T G.711 A-law";
|
||||
case 'ALAW': return "8-bit ITU-T G.711 A-law";
|
||||
case 'ulaw': return "8-bit ITU-T G.711 µ-law";
|
||||
case 'ULAW': return "8-bit ITU-T G.711 µ-law";
|
||||
case 'ima4': return "IMA 4:1";
|
||||
case 'MAC3': return "MACE 3-to-1";
|
||||
case 'MAC6': return "MACE 6-to-1";
|
||||
case 'QDMC': return "QDesign Music";
|
||||
case 'Qclp': return "Qualcomm PureVoice";
|
||||
case 'rt24': return "RT24 50:1";
|
||||
case 'rt29': return "RT29 50:1";
|
||||
default:
|
||||
sprintf(s, "unknown compression %c%c%c%c",
|
||||
(int)((compression >> 24) & 0xff),
|
||||
(int)((compression >> 16) & 0xff),
|
||||
(int)((compression >> 8) & 0xff),
|
||||
(int)(compression & 0xff));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,413 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <DataIO.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include "aiff_reader.h"
|
||||
|
||||
#define TRACE_THIS 1
|
||||
#if TRACE_THIS
|
||||
#define TRACE printf
|
||||
#else
|
||||
#define TRACE(a...)
|
||||
#endif
|
||||
|
||||
#define BUFFER_SIZE 16384
|
||||
|
||||
#define FOURCC(a,b,c,d) ((((uint32)(a)) << 24) | (((uint32)(b)) << 16) | (((uint32)(c)) << 8) | ((uint32)(d)))
|
||||
#define UINT16(a) ((uint16)B_BENDIAN_TO_HOST_INT16((a)))
|
||||
#define UINT32(a) ((uint32)B_BENDIAN_TO_HOST_INT32((a)))
|
||||
|
||||
aiffReader::aiffReader()
|
||||
{
|
||||
TRACE("aiffReader::aiffReader\n");
|
||||
fBuffer = 0;
|
||||
}
|
||||
|
||||
|
||||
aiffReader::~aiffReader()
|
||||
{
|
||||
if (fBuffer)
|
||||
free(fBuffer);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
aiffReader::Copyright()
|
||||
{
|
||||
return ".au & .snd reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen";
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
aiffReader::Sniff(int32 *streamCount)
|
||||
{
|
||||
TRACE("aiffReader::Sniff\n");
|
||||
|
||||
fSource = dynamic_cast<BPositionIO *>(Reader::Source());
|
||||
if (!fSource) {
|
||||
TRACE("aiffReader::Sniff: not a BPositionIO\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
int64 filesize = Source()->Seek(0, SEEK_END);
|
||||
if (filesize < 42) {
|
||||
TRACE("aiffReader::Sniff: File too small\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
aiff_chunk aiff;
|
||||
|
||||
if (sizeof(aiff) != Source()->ReadAt(0, &aiff, sizeof(aiff))) {
|
||||
TRACE("aiffReader::Sniff: aiff_chunk reading failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (UINT32(aiff.chunk_id) != FOURCC('F','O','R','M')
|
||||
|| (UINT32(aiff.aiff_id) != FOURCC('A','I','F','F')
|
||||
&& UINT32(aiff.aiff_id) != FOURCC('A','I','F','C'))) {
|
||||
TRACE("aiffReader::Sniff: aiff not recognized\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
comm_chunk comm;
|
||||
ssnd_chunk ssnd;
|
||||
int64 pos = sizeof(aiff);
|
||||
|
||||
fDataStart = 0;
|
||||
fDataSize = 0;
|
||||
|
||||
// read all chunks and search for "COMM" and "SSND", everything else is ignored
|
||||
bool foundCOMM = false;
|
||||
bool foundSSND = false;
|
||||
while (pos + sizeof(chunk_struct) <= filesize) {
|
||||
chunk_struct chunk;
|
||||
if (sizeof(chunk) != Source()->ReadAt(pos, &chunk, sizeof(chunk))) {
|
||||
TRACE("aiffReader::Sniff: chunk header reading failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
pos += sizeof(chunk);
|
||||
switch (UINT32(chunk.chunk_id)) {
|
||||
case FOURCC('C','O','M','M'):
|
||||
{
|
||||
if (foundCOMM)
|
||||
break;
|
||||
uint32 size = UINT32(chunk.chunk_size);
|
||||
if (size >= 18) {
|
||||
size = min_c(size, sizeof(comm));
|
||||
if (size != (uint32)Source()->ReadAt(pos, &comm, size)) {
|
||||
TRACE("aiffReader::Sniff: COMM chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
if (size < 22)
|
||||
comm.compression_id = B_HOST_TO_BENDIAN_INT32(FOURCC('N','O','N','E'));
|
||||
foundCOMM = true;
|
||||
} else {
|
||||
TRACE("aiffReader::Sniff: COMM chunk too small\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FOURCC('S','S','N','D'):
|
||||
{
|
||||
if (foundSSND)
|
||||
break;
|
||||
uint32 size = UINT32(chunk.chunk_size);
|
||||
if (size >= sizeof(ssnd)) {
|
||||
if (sizeof(ssnd) != Source()->ReadAt(pos, &ssnd, sizeof(ssnd))) {
|
||||
TRACE("aiffReader::Sniff: SSND chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
fDataStart = pos + sizeof(ssnd) + UINT32(ssnd.offset);
|
||||
fDataSize = UINT32(chunk.chunk_size) - sizeof(ssnd);
|
||||
if (pos + fDataSize + sizeof(ssnd) > filesize)
|
||||
fDataSize = filesize - pos - sizeof(ssnd);
|
||||
foundSSND = true;
|
||||
} else {
|
||||
TRACE("aiffReader::Sniff: SSND chunk too small\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TRACE("aiffReader::Sniff: ignoring chunk 0x%08lx of %lu bytes\n", UINT32(chunk.chunk_id), UINT32(chunk.chunk_size));
|
||||
break;
|
||||
}
|
||||
pos += UINT32(chunk.chunk_size);
|
||||
pos += (pos & 1);
|
||||
}
|
||||
|
||||
if (!foundCOMM) {
|
||||
TRACE("aiffReader::Sniff: couldn't find format chunk\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (!foundSSND) {
|
||||
TRACE("aiffReader::Sniff: couldn't find data chunk\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("aiffReader::Sniff: we found something that looks like:\n");
|
||||
|
||||
TRACE(" channel_count %d\n", UINT16(comm.channel_count));
|
||||
TRACE(" frame_count %ld\n", UINT32(comm.frame_count));
|
||||
TRACE(" bits_per_sample %d\n", UINT16(comm.bits_per_sample));
|
||||
TRACE(" sample_rate %ld\n", DecodeFrameRate(comm.sample_rate));
|
||||
TRACE(" compression_id %s\n", string_for_compression(UINT32(comm.compression_id)));
|
||||
TRACE(" offset %ld\n", UINT32(ssnd.offset));
|
||||
TRACE(" block_size %ld\n", UINT32(ssnd.block_size));
|
||||
|
||||
fChannelCount = UINT16(comm.channel_count);
|
||||
fFrameCount = UINT32(comm.frame_count);
|
||||
fFrameRate = DecodeFrameRate(comm.sample_rate);
|
||||
fDuration = (1000000LL * fFrameCount) / fFrameRate;
|
||||
fValidBitsPerSample = UINT16(comm.bits_per_sample);
|
||||
fBytesPerSample = (fValidBitsPerSample + 7) / 8;
|
||||
fBytesPerFrame = fBytesPerSample * fChannelCount;
|
||||
fFormatCode = UINT32(comm.compression_id);
|
||||
|
||||
if (fChannelCount < 1)
|
||||
fChannelCount = 1;
|
||||
if (fFrameRate < 1)
|
||||
fFrameRate = 44100;
|
||||
|
||||
if (fBytesPerSample == 0) {
|
||||
TRACE("aiffReader::Sniff: sample format not recognized\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
switch (fFormatCode) {
|
||||
case FOURCC('N','O','N','E'):
|
||||
case FOURCC('F','L','3','2'):
|
||||
case FOURCC('f','l','3','2'):
|
||||
case FOURCC('f','l','6','4'):
|
||||
fRaw = true;
|
||||
break;
|
||||
default:
|
||||
fRaw = false;
|
||||
break;
|
||||
}
|
||||
|
||||
fPosition = 0;
|
||||
|
||||
fBufferSize = (BUFFER_SIZE / fBytesPerFrame) * fBytesPerFrame;
|
||||
fBuffer = malloc(fBufferSize);
|
||||
|
||||
TRACE(" fDataStart %Ld\n", fDataStart);
|
||||
TRACE(" fDataSize %Ld\n", fDataSize);
|
||||
TRACE(" fFrameCount %Ld\n", fFrameCount);
|
||||
TRACE(" fDuration %Ld\n", fDuration);
|
||||
TRACE(" fChannelCount %d\n", fChannelCount);
|
||||
TRACE(" fFrameRate %ld\n", fFrameRate);
|
||||
TRACE(" fValidBitsPerSample %d\n", fValidBitsPerSample);
|
||||
TRACE(" fBytesPerSample %d\n", fBytesPerSample);
|
||||
TRACE(" fBytesPerFrame %d\n", fBytesPerFrame);
|
||||
TRACE(" fFormatCode %ld\n", fFormatCode);
|
||||
TRACE(" fRaw %d\n", fRaw);
|
||||
|
||||
BMediaFormats formats;
|
||||
if (fRaw) {
|
||||
// a raw PCM format
|
||||
media_format_description description;
|
||||
description.family = B_BEOS_FORMAT_FAMILY;
|
||||
description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
|
||||
formats.GetFormatFor(description, &fFormat);
|
||||
fFormat.u.raw_audio.frame_rate = fFrameRate;
|
||||
fFormat.u.raw_audio.channel_count = fChannelCount;
|
||||
switch (fFormatCode) {
|
||||
case FOURCC('N','O','N','E'):
|
||||
switch (fBytesPerSample) {
|
||||
case 1:
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_CHAR;
|
||||
break;
|
||||
case 2:
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
break;
|
||||
case 3:
|
||||
// XXX broken
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
|
||||
break;
|
||||
case 4:
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
|
||||
break;
|
||||
default:
|
||||
TRACE("aiffReader::Sniff: unknown bytes per sample for raw format\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
break;
|
||||
case FOURCC('F','L','3','2'):
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
break;
|
||||
case FOURCC('f','l','3','2'):
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
break;
|
||||
case FOURCC('f','l','6','4'):
|
||||
// XXX broken
|
||||
fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
break;
|
||||
default:
|
||||
TRACE("aiffReader::Sniff: unknown raw format\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
fFormat.u.raw_audio.byte_order = B_MEDIA_BIG_ENDIAN;
|
||||
fFormat.u.raw_audio.buffer_size = fBufferSize;
|
||||
} else {
|
||||
// some encoded format
|
||||
media_format_description description;
|
||||
description.family = B_AIFF_FORMAT_FAMILY;
|
||||
description.u.aiff.codec = fFormatCode;
|
||||
formats.GetFormatFor(description, &fFormat);
|
||||
fFormat.u.encoded_audio.output.frame_rate = fFrameRate;
|
||||
fFormat.u.encoded_audio.output.channel_count = fChannelCount;
|
||||
}
|
||||
|
||||
*streamCount = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
aiffReader::GetFileFormatInfo(media_file_format *mff)
|
||||
{
|
||||
mff->capabilities = media_file_format::B_READABLE
|
||||
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||
mff->family = B_MISC_FORMAT_FAMILY;
|
||||
mff->version = 100;
|
||||
strcpy(mff->mime_type, "audio/x-aiff");
|
||||
strcpy(mff->file_extension, "aiff");
|
||||
strcpy(mff->short_name, "AIFF / AIFF-C");
|
||||
strcpy(mff->pretty_name, "Audio Interchange File Format");
|
||||
}
|
||||
|
||||
status_t
|
||||
aiffReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
aiffReader::FreeCookie(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
aiffReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||
media_format *format, void **infoBuffer, int32 *infoSize)
|
||||
{
|
||||
*frameCount = fFrameCount;
|
||||
*duration = fDuration;
|
||||
*format = fFormat;
|
||||
*infoBuffer = 0;
|
||||
*infoSize = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
aiffReader::Seek(void *cookie,
|
||||
uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time)
|
||||
{
|
||||
int64 pos;
|
||||
|
||||
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
|
||||
if (fRaw)
|
||||
pos = *frame * fBytesPerFrame;
|
||||
else
|
||||
pos = (*frame * fDataSize) / fFrameCount;
|
||||
pos = (pos / fBytesPerFrame) * fBytesPerFrame; // round down to a block start
|
||||
TRACE("aiffReader::Seek to frame %Ld, pos %Ld\n", *frame, pos);
|
||||
} else if (seekTo & B_MEDIA_SEEK_TO_TIME) {
|
||||
if (fRaw)
|
||||
pos = (*time * fFrameRate * fBytesPerFrame) / 1000000LL;
|
||||
else
|
||||
pos = (*time * fDataSize) / fDuration;
|
||||
pos = (pos / fBytesPerFrame) * fBytesPerFrame; // round down to a block start
|
||||
TRACE("aiffReader::Seek to time %Ld, pos %Ld\n", *time, pos);
|
||||
} else {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (fRaw)
|
||||
*frame = pos / fBytesPerFrame;
|
||||
else
|
||||
*frame = (pos * fFrameCount) / fDataSize;
|
||||
*time = (*frame * 1000000LL) / fFrameRate;
|
||||
|
||||
TRACE("aiffReader::Seek newtime %Ld\n", *time);
|
||||
TRACE("aiffReader::Seek newframe %Ld\n", *frame);
|
||||
|
||||
if (pos < 0 || pos > fDataSize) {
|
||||
TRACE("aiffReader::Seek invalid position %Ld\n", pos);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fPosition = pos;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
aiffReader::GetNextChunk(void *cookie,
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
// XXX it might be much better to not return any start_time information for encoded formats here,
|
||||
// XXX and instead use the last time returned from seek and count forward after decoding.
|
||||
mediaHeader->start_time = ((fPosition / fBytesPerFrame) * 1000000LL) / fFrameRate;
|
||||
mediaHeader->file_pos = fDataStart + fPosition;
|
||||
|
||||
int64 maxreadsize = fDataSize - fPosition;
|
||||
int32 readsize = fBufferSize;
|
||||
if (maxreadsize < readsize)
|
||||
readsize = maxreadsize;
|
||||
if (readsize == 0)
|
||||
return B_LAST_BUFFER_ERROR;
|
||||
|
||||
if (readsize != Source()->ReadAt(fDataStart + fPosition, fBuffer, readsize)) {
|
||||
TRACE("aiffReader::GetNextChunk: unexpected read error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// XXX if the stream has more than two channels, we need to reorder channel data here
|
||||
|
||||
fPosition += readsize;
|
||||
*chunkBuffer = fBuffer;
|
||||
*chunkSize = readsize;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
uint32
|
||||
aiffReader::DecodeFrameRate(void *_80bit_float)
|
||||
{
|
||||
// algorithm from http://www.borg.com/~jglatt/tech/aiff.htm
|
||||
uint32 mantissa;
|
||||
uint32 last;
|
||||
uint32 exp;
|
||||
|
||||
mantissa = (uint32)B_BENDIAN_TO_HOST_INT32(*(uint32 *)((char *)_80bit_float + 2));
|
||||
exp = 30 - *(uint8 *)((char *)_80bit_float + 1);
|
||||
if (exp > 32)
|
||||
return 0;
|
||||
last = 0;
|
||||
while (exp--) {
|
||||
last = mantissa;
|
||||
mantissa >>= 1;
|
||||
}
|
||||
if (last & 1)
|
||||
mantissa++;
|
||||
return mantissa;
|
||||
}
|
||||
|
||||
|
||||
Reader *
|
||||
aiffReaderPlugin::NewReader()
|
||||
{
|
||||
return new aiffReader;
|
||||
}
|
||||
|
||||
|
||||
MediaPlugin *instantiate_plugin()
|
||||
{
|
||||
return new aiffReaderPlugin;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "ReaderPlugin.h"
|
||||
#include "aiff.h"
|
||||
|
||||
class aiffReader : public Reader
|
||||
{
|
||||
public:
|
||||
aiffReader();
|
||||
~aiffReader();
|
||||
|
||||
const char *Copyright();
|
||||
|
||||
status_t Sniff(int32 *streamCount);
|
||||
|
||||
void GetFileFormatInfo(media_file_format *mff);
|
||||
|
||||
status_t AllocateCookie(int32 streamNumber, void **cookie);
|
||||
status_t FreeCookie(void *cookie);
|
||||
|
||||
status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
|
||||
media_format *format, void **infoBuffer, int32 *infoSize);
|
||||
|
||||
status_t Seek(void *cookie,
|
||||
uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time);
|
||||
|
||||
status_t GetNextChunk(void *cookie,
|
||||
void **chunkBuffer, int32 *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
private:
|
||||
uint32 DecodeFrameRate(void *_80bit_float);
|
||||
|
||||
BPositionIO *Source() { return fSource; }
|
||||
|
||||
private:
|
||||
BPositionIO * fSource;
|
||||
|
||||
media_format fFormat;
|
||||
int64 fDataStart;
|
||||
int64 fDataSize;
|
||||
|
||||
int64 fFrameCount;
|
||||
bigtime_t fDuration;
|
||||
|
||||
bool fRaw;
|
||||
|
||||
int64 fPosition;
|
||||
|
||||
int fChannelCount;
|
||||
int32 fFrameRate;
|
||||
int fValidBitsPerSample;
|
||||
int fBytesPerSample;
|
||||
int fBytesPerFrame;
|
||||
uint32 fFormatCode;
|
||||
|
||||
void * fBuffer;
|
||||
int32 fBufferSize;
|
||||
};
|
||||
|
||||
|
||||
class aiffReaderPlugin : public ReaderPlugin
|
||||
{
|
||||
public:
|
||||
Reader *NewReader();
|
||||
};
|
||||
|
||||
MediaPlugin *instantiate_plugin();
|
||||
Reference in New Issue
Block a user