-------------------------------------------------- kissdx back-to-back audio playback - Specification -------------------------------------------------- RATIONALE kissdx can already play audio files in sequence from a directory or a playlist. However, when one song ends and the next one starts, there is always a short pause inbetween, and some times also an audible click. Playing songs back to back means that none of these occur, and e.g. a ripped audio CD can be enjoyed exactly as it was intended. INITIAL THOUGHTS AND NOTES Playing back a sequence of audio files should be possible without doing any re-encoding on the server. Both OGG Vorbis and MP3 are streamable formats, and just attaching one audio file the end of the previous one should be a possible solution, probably taking care to skip any metadata (ID3 tags, etc.) in the process. WAV files could be processed in the same manner? We should probably construct (filetype dependent) metadata (ID3 etc) in the new combined file. Maybe this is not necessary though: Maybe the metadata in the individual files can just be streamed with the contents? We need to study the MP3 / OGG / WAV file formats (headers) to determine. Playing all mp3 files in a folder back-to-back thus means presenting a single combined mp3 file to the player. When the player asks for data in this large non-existant file, kissdx must trap this and return data from whichever audio file is placed at the requested byte position in the combined file. This must happen quickly, so kissdx should probably store in memory some info on the combined file that makes this a quick process. If a folder / a playlist contains audio files of differing formats, e.g. some mp3 and some ogg, only one type of files can be played back-to-back. IMPLEMENTATION When a folder or a playlist is presented as a listing on the player, we will present additional pseudo-directories at the top (or bottom) of the listing: One line per audio file type in that directory. E.g.: [Play all mp3 files head to head] [Play all ogg files head to head] [Play all wav files head to head] When such a pseudo-directory is selected on the player, kissdx will construct info about that combined file (if not already in memory), and will serve the data that corresponds to the position & chunk size requested by the player. CONSIDERATION: THE [RECENTLY USED] FOLDER We must find a way to store back-to-back files in the .recent folder and also to process them correctly when selected from the .recent folder. STATUS Implemented in kissdx 0.13-10. *********************************************** *********************************************** ************* Further development ************* *********************************************** *********************************************** ----------------------------------------------------------------- kissdx back-to-back audio playback enhancement #1 - Specification ----------------------------------------------------------------- ELIMINATING GAPS COMPLETELY BY REMOVING ALL ID3 TAGS/METADATA RATIONALE The current implementation just concatenates media files into a bigger virtual file that is served to the player. This removes most of the pauses between tracks, but there is still a litte delay as the MP3 ID tag for each track is sent to and skipped by the player. It should be easy to locate the MP3 ID tags if they are at the start or end of each MP3 file. Then they can be eliminated from the combined virtual file and never be seen by the player. The same procedure should be possible for OGG files. Probably not necessary! IMPLEMENTATION As we compose the info structure describing the combined file in the compose_combinedfile() function, we will open each media file in turn and read the start of the file looking for an ID tag. If an ID tag is not found at the start of the file, we will read the last 2000 bytes of the file and scan that part of the file for an ID tag, verifying that the ID tag (if found) extends to the end of the media file. We should need to detect a single ID tag (start or end of file), two ID tags (start and end of file) or no ID tag. We must add a new field to the b2b_mediafile_t type so we can remember where IN THE MEDIA FILE the actual media content (e.g. real content minus ID tag) starts (i.e. when the ID tag is at the start of the file): typedef struct b2b_mediafile_s { char * filename; // Media filename, NOT including path off_t offset; // Offset of start of media file in combined file u_int64_t size; // Size of media file off_t mediafile_offset; // Offset of start of media content in media file } b2b_mediafile_t; If an ID tag is found, we remove it from the description of the combined file by changing either the offset or the size of the media file in our info structure. We add code like this to compose_combinedfile(), after the assignments inside the for loop: Set Cached_CombinedFile.mediafiles[n]->mediafile_offset = 0. Open media file. Look for an ID tag as described above. Close media file. If the ID tag was found at all: Decrease Cached_CombinedFile.mediafiles[n]->size by the size of the ID tag. If the ID tag was found at the start of the media file: Set Cached_CombinedFile.mediafiles[n]->mediafile_offset = the size of the ID tag. End If End If We must also reduce the running offset by the size of the ID tag, so that the next media file will start at the correct (earlier than the real) position in the combined file. Then the final size of the entire combined file will be reduced by the combined size of all ID tags found. Exceptions: We should NOT remove an ID tag that is found at the start of the first media file. We should NOT remove an ID tag that is found at the end of the last media file. These ID tags will be at the start / end of the combined virtual file, so they will not induce audible skips. This way the player will have some info about the combined file although it is not entirely correct. SOME MP3 ID TAG INFO ID3 v1 and v1.1 tags are at the end of the media file. These tags are 128 bytes long and start with the letters "TAG", so should be easy to identify. ID3v2 tags appear at the start of the media file. The following is quoted from http://www.id3.org/id3v2.4.0-structure 3.1. ID3v2 header The first part of the ID3v2 tag is the 10 byte tag header, laid out as follows: ID3v2/file identifier "ID3" ID3v2 version $04 00 ID3v2 flags %abcd0000 ID3v2 size 4 * %0xxxxxxx The first three bytes of the tag are always "ID3", to indicate that this is an ID3v2 tag, directly followed by the two version bytes. The first byte of ID3v2 version is its major version, while the second byte is its revision number. In this case this is ID3v2.4.0. [...] The ID3v2 tag size is stored as a 32 bit synchsafe integer (section 6.2), making a total of 28 effective bits (representing up to 256MB). The ID3v2 tag size is the sum of the byte length of the extended header, the padding and the frames after unsynchronisation. If a footer is present this equals to ('total size' - 20) bytes, otherwise ('total size' - 10) bytes. An ID3v2 tag can be detected with the following pattern: $49 44 33 yy yy xx zz zz zz zz Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80. 6.2. Synchsafe integers In some parts of the tag it is inconvenient to use the unsychronisation scheme because the size of unsynchronised data is not known in advance, which is particularly problematic with size descriptors. The solution in ID3v2 is to use synchsafe integers, in which there can never be any false synchs. Synchsafe integers are integers that keep its highest bit (bit 7) zeroed, making seven bits out of eight available. Thus a 32 bit synchsafe integer can store 28 bits of information. Example: 255 (%11111111) encoded as a 16 bit synchsafe integer is 383 (%00000001 01111111). STATUS Implemented in kissdx 0.13-12. ----------------------------------------------------------------- kissdx back-to-back audio playback enhancement #2 - Specification ----------------------------------------------------------------- EXTENDING B2B (GAPLESs) PLAYBACK TO COVER PLAYLISTS RATIONALE Gapless playback is possible for a directory. It should be possible for playlists too. An advantage of this is that a playlist can describe the original album correctly when the alphabetically ordered file listing does not. IMPLEMENTATION TBD. STATUS Not implemented.