/**************************************************************************** * * RealNetworks Transform Architecture * * $Id: rtaaudioformat.h,v 1.3.4.1 2002/06/21 00:04:49 rbunnage Exp $ * * Copyright (C) 1995-2001 RealNetworks, Inc. All rights reserved. * * http://www.real.com/devzone * * This program contains proprietary information of RealNetworks, Inc, * and is licensed subject to restrictions on use and distribution. * * Defines enums and macros for the audio format field. * * These enums transport the datatype of audio samples. There are several * aspects to the data type. The most basic is, of course, endianness (and * yes, there are more endiannesses than little- and big-endian, albeit those * two do cover 99% of the cases). * * The second aspect -- byte packing -- is relevant especially for 24-bit data * types. These could be packed space-efficiently into 3 bytes per sample, but * that format is very unwieldy to work with (on a Pentium, instead of one * aligned 32-bit access to memory, you'll need three 8-bit accesses, and two * shifts and additions). * This points out that for fast execution, audio samples should be packed into * the native types that your CPU supports -- usually 16-bit (short) and 32-bit * (int), in (machine-)native endianness. * * Most audio transform filters will only support these two datatypes. That is, * they will advertise RS_AUDIO_FORMAT_NE_16_2 and RS_AUDIO_FORMAT_NE_32_4 as * supported. At configuration time, they crack the enums using the * RS_BITS_PER_SAMPLE and/or RS_BYTES_PER_SAMPLE macros. * * On the input side, sample formats could run the whole gamut. A format * converter filter takes care of casting any of the possible input formats * into the canonical format (16-bit or 32-bit, native endianness). * * If you are writing an input filter, you don't need to concern yourself with * converting samples to the right endianness or byte packing -- just make sure * you accurately report to the system which datatype is being delivered. For * bits/sample, that's fairly straightforward. Bytes/sample is usually signalled * in the header of the sound file you are reading, or is implied by the specs. * The same goes true for (sound) capture cards. * * Endianness is usually, but not always, determined by the endianness of the * file you are reading, *not by the machine endianness*! If you read a * WAV/RIFF file, endianness is little; if you read an AIFF file, it is * big-endian. However, if your code does any endianness conversions (towards * native, hopefully), the endianness to report would be native-endian. * * It is a matter of taste how you declare the endianness if the samples are * supplied by an operating-system function. If you get the samples from some * MacOS function, you could decide to report big-endian, since that is the * endianness of about all the Macs out there. On the other hand, are you * *sure* that that MacOS will run on a little-endian machine? I would opt for * using "native" -- that is equivalent on your machine, but will continue to * work if the source is ever compiled for a little-endian machine. * * */ #ifndef rtaaudiosampleformat_h #define rtaaudiosampleformat_h #define RS_ENDIANNESS_LITTLE 0 #define RS_ENDIANNESS_BIG 1 #if defined _WIN32 || defined _UNIX #define RS_ENDIANNESS_NATIVE RS_ENDIANNESS_LITTLE #else #error need to define ENDIANNESS for future platforms //#define RS_ENDIANNESS_NATIVE RS_ENDIANNESS_BIG #endif /* macro to generate a sample format */ #define RS_MAKE_SAMPLE_FORMAT( endianness, bitsPerSample, bytesPerSample ) \ ( ((bitsPerSample)<<6) | ((bytesPerSample)<<2) | ((endianness)) ) /* macros to crack the sample format struct sampleFormat { int bits_per_sample:7 ; int bytes_per_sample : 4 ; int endianness : 2 ; } */ #define RS_BITS_PER_SAMPLE(e) (((e) >> 6) & 0x7f) #define RS_BYTES_PER_SAMPLE(e) (((e) >> 2) & 0x0f) #define RS_ENDIANNESS(e) ( (e) & 0x02) enum RSEAudioSampleFormat { RS_AUDIO_FORMAT_INVALID = 0, RS_AUDIO_FORMAT_LE_8_1 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 8, 1 ), RS_AUDIO_FORMAT_BE_8_1 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 8, 1 ), RS_AUDIO_FORMAT_NE_8_1 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 8, 1 ), RS_AUDIO_FORMAT_LE_16_2 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 16,2 ), RS_AUDIO_FORMAT_BE_16_2 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 16,2 ), RS_AUDIO_FORMAT_NE_16_2 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 16,2 ), RS_AUDIO_FORMAT_LE_20_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 20,3 ), RS_AUDIO_FORMAT_BE_20_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 20,3 ), RS_AUDIO_FORMAT_NE_20_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 20,3 ), RS_AUDIO_FORMAT_LE_20_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 20,4 ), RS_AUDIO_FORMAT_BE_20_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 20,4 ), RS_AUDIO_FORMAT_NE_20_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 20,4 ), RS_AUDIO_FORMAT_LE_24_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 24,3 ), RS_AUDIO_FORMAT_BE_24_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 24,3 ), RS_AUDIO_FORMAT_NE_24_3 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 24,3 ), RS_AUDIO_FORMAT_LE_24_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 24,4 ), RS_AUDIO_FORMAT_BE_24_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 24,4 ), RS_AUDIO_FORMAT_NE_24_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 24,4 ), RS_AUDIO_FORMAT_LE_32_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_LITTLE, 32,4 ), RS_AUDIO_FORMAT_BE_32_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_BIG, 32,4 ), RS_AUDIO_FORMAT_NE_32_4 = RS_MAKE_SAMPLE_FORMAT( RS_ENDIANNESS_NATIVE, 32,4 ), }; enum RSEAudioChannelFormat { RS_AUDIO_CHANNEL_FORMAT_INVALID= 0x0, RS_AUDIO_FRONT_LEFT = 0x1, RS_AUDIO_FRONT_RIGHT = 0x2, RS_AUDIO_FRONT_CENTER = 0x4, RS_AUDIO_LOW_FREQUENCY = 0x8, RS_AUDIO_BACK_LEFT = 0x10, RS_AUDIO_BACK_RIGHT = 0x20, RS_AUDIO_FRONT_LEFT_OF_CENTER = 0x40, RS_AUDIO_FRONT_RIGHT_OF_CENTER = 0x80, RS_AUDIO_BACK_CENTER = 0x100, RS_AUDIO_SIDE_LEFT = 0x200, RS_AUDIO_SIDE_RIGHT = 0x400, RS_AUDIO_TOP_CENTER = 0x800, RS_AUDIO_TOP_FRONT_LEFT = 0x1000, RS_AUDIO_TOP_FRONT_CENTER = 0x2000, RS_AUDIO_TOP_FRONT_RIGHT = 0x4000, RS_AUDIO_TOP_BACK_LEFT = 0x8000, RS_AUDIO_TOP_BACK_CENTER = 0x10000, RS_AUDIO_TOP_BACK_RIGHT = 0x20000, RS_AUDIO_RESERVED = 0x80000000, // convenience defines RS_AUDIO_MONO = RS_AUDIO_FRONT_CENTER, RS_AUDIO_STEREO = RS_AUDIO_FRONT_LEFT | RS_AUDIO_FRONT_RIGHT, RS_AUDIO_5 = RS_AUDIO_FRONT_LEFT | RS_AUDIO_FRONT_RIGHT | RS_AUDIO_FRONT_CENTER | RS_AUDIO_BACK_LEFT | RS_AUDIO_BACK_RIGHT, RS_AUDIO_5_1 = RS_AUDIO_FRONT_LEFT | RS_AUDIO_FRONT_RIGHT | RS_AUDIO_FRONT_CENTER | RS_AUDIO_BACK_LEFT | RS_AUDIO_BACK_RIGHT | RS_AUDIO_LOW_FREQUENCY }; static unsigned int RS_MAKE_CHANNELMASK(int nchannels) { static unsigned int mask[3] = { 0, RS_AUDIO_MONO, RS_AUDIO_STEREO } ; return (nchannels > 0 && nchannels <= 2) ? mask[nchannels] : 0 ; } static int RS_NCHANNELS_IN_MASK(int m) { int n = 0; for (; m ; m>>=1) { n += (m & 1) ; } return n; } #endif /* rtaaudioformat_h */