----------------------------------- kissdx FLAC support - Specification ----------------------------------- RATIONALE kissdx can already serve mp3, ogg etc. to KiSS players, but these are lossy formats. A wav file renamed to *.mp3 can also be played by KiSS players (at least by the DP-600) thus giving the best possible audio quality at the cost of larger files. FLAC is lossless like wav and compressed like mp3, etc., giving us the best of both worlds. There is already a libFLAC that we can use on the NSLU2 and other platforms. INITIAL THOUGHTS AND NOTES libFLAC is based on callback functions. This should not be a problem as we already have a tight loop in the ACTION handler that serves the entire file. The plan is to let the KiSS player see the data as if it was coming from a RIFF WAV file, with an mp3 extension to make the player list it on screen. The pseudo-WAV file will have a RIFF header and one Format Chunk plus one Data Chunk. The Format Chunk comes before the Data Chunk. The structure of the RIFF header (including data type id = "WAVE"): typedef struct { char id[4]; // Will be "RIFF" long remainingFileSize; // Will be file size minus 8 char wave_id[4]; // Will be "WAVE" } RiffHeader_Wave; The Format Chunk will have wFormatTag = 1, a standard PCM encoded wav with no extra info. This makes the Format Chunk 24 bytes long. The other fields of the Format Chunk will be specified later. This is the structure of the Format Chunk: typedef struct { char chunkID[4]; // Will be "fmt " long chunkSize; // Will be 24 short wFormatTag; // Will be 1 for uncompressed PCM unsigned short wChannels; // 2 for stereo, depends on source unsigned long dwSamplesPerSec; unsigned long dwAvgBytesPerSec; unsigned short wBlockAlign; unsigned short wBitsPerSample; // Typically 16, depends on source } FormatChunk; The Data Chunk follows the Format Chunk and extends to the end of the wav file. The structure of the Data Chunk header typedef struct { char chunkID[4]; // Will be "data" long chunkSize; // Will be file size minus 44 } DataHeader; The total offset before the PCM wave samples start will be: 12 bytes for RIFF header ("RIFF" + (DWORD)length_of_rest_of_file + "WAVE") 24 bytes for Format Chunk ("fmt " + ...........) 8 bytes for Data Chunk header ("data" + (DWORD)length_of_wave_data) -- 44 bytes in total We will use libFLAC's "seekable stream decoder" interface to access the FLAC file. We can call FLAC__metadata_get_streaminfo() to get information for filling in the RIFF header and the Format Chunk. Hopefully this will give enough info... We can call FLAC__seekable_stream_decoder_seek_absolute() to position on the first sample of the data chunk that the KiSS player asks for. We calculate the FLAC sample no. from the wav_byte_offset requested by the player as flac_sample_no = 44 + (wav_byte_offset / ((bits_per_sampe / 8) * no_of_channels)); The values of bits_per_sampe and no_of_channels will depend on the FLAC file we're playing, but these are typical values: bits_per_sampe = 16 no_of_channels = 2 STATUS Not implemented as of 2007-02-09.