/** * Play one step of the buffer */ int play_step_music_buffer(music_buffer_t *music_buf) { size_t ret = 0; if (lock_music_buffer(music_buf)) return 1; MY_READ(music_buf->info.file, music_buf->buf, music_buf->buf_size); size_t bytes = ret; if (bytes == 0) { if (!feof(music_buf->info.file)) { unlock_music_buffer(music_buf); return 0; } else { fprintf(stderr, "An error occured while reading the file.\n"); unlock_music_buffer(music_buf); return 1; } } unlock_music_buffer(music_buf); ret = write(music_buf->fd_dsp, music_buf->buf, bytes); // An error may happen when stopping playback if (ret != bytes && music_buf->playing) { fprintf(stderr, "Writing to the sound device failed.\n"); return 2; } return 0; }
/** * Open a music file in AU or WAVE format * Please call fclose(file_info->file) to free the file descriptor */ int open_music_file(const char *file_name, music_file_t *file_info) { // Open file file_info->file = fopen (file_name, "rb"); if (file_info->file == NULL) { fprintf(stderr, "Couldn't open the file!\n"); return 2; } // Look for magic number to determine file type int ret; uint32_t magic_number; MY_READ(file_info->file, & magic_number, sizeof(magic_number)); magic_number = ntohl (magic_number); if (magic_number == 0x52494646) { // Seems to be a RIFF file. Try to see if it's a WAVE one. ret = wave_opener(file_info); } else if (magic_number == 0x2e736e64) { // Decode file header ret = au_opener(file_info); } else { fprintf(stderr, "File format not recognized.\n"); fclose(file_info->file); return 2; } if (ret) { fprintf(stderr, "Header parsing failed! File may have been corrupted.\n"); fclose(file_info->file); return 2; } return 0; }
static ssize_t fullRead (int fd, char *buf, size_t count) // Retry partial or EAGAIN writes until count is completely written. { size_t bytesread = 0; while (bytesread < count) { ssize_t rv = MY_READ (fd, buf+bytesread, count-bytesread); if (rv < 0) { if ((errno == EAGAIN) || (errno == EINTR)) { continue; } return rv; } else if (rv == 0) { return bytesread; } bytesread += rv; } assert (bytesread == count); return bytesread; }
/** * Read info in WAV files. */ int wave_opener(music_file_t * file_info) { // Apart from the magic numbers, the RIFF spec says that everything // is stored in little-endian. int ret = 0; FILE * file = file_info -> file; uint32_t file_size; MY_READ(file, & file_size, sizeof(file_size)); file_size = U32_TO_LE(file_size); file_size += 8; printf("[WAV] File size: %u.\n", file_size); uint32_t magic_number; MY_READ(file, & magic_number, sizeof(magic_number)); magic_number = ntohl (magic_number); if (magic_number != 0x57415645) { fprintf(stderr, "This RIFF file not a WAVE file.\n"); return 1; } uint32_t magic_number_header; MY_READ(file, & magic_number_header, sizeof(magic_number_header)); magic_number_header = ntohl (magic_number_header); if (magic_number_header != 0x666d7420) { fprintf(stderr, "WAVE file ERROR: no header!!\n"); return 1; } uint32_t header_size; MY_READ(file, & header_size, sizeof(header_size)); header_size = U32_TO_LE (header_size); printf("[WAV] Header size: %u.\n", header_size); uint16_t encoding; MY_READ(file, & encoding, sizeof(encoding)); encoding = U16_TO_LE (encoding); printf("[WAV] WAVE encoding format: %u.\n", encoding); if (encoding != 1) { fprintf(stderr, "Encoding not supported. Sorry...\n"); return 1; } uint16_t channels; MY_READ(file, & channels, sizeof(channels)); channels = U16_TO_LE (channels); printf("[WAV] Nb of channels: %u.\n", channels); file_info -> channels = channels; uint32_t sample_rate; MY_READ(file, & sample_rate, sizeof(sample_rate)); sample_rate = U32_TO_LE (sample_rate); printf("[WAV] Sample rate: %u.\n", sample_rate); file_info -> sample_rate = sample_rate; uint32_t byte_rate; MY_READ(file, & byte_rate, sizeof(byte_rate)); byte_rate = U32_TO_LE (byte_rate); printf("[WAV] Byte rate: %u.\n", byte_rate); uint16_t block_align; MY_READ(file, & block_align, sizeof(block_align)); block_align = U16_TO_LE (block_align); printf("[WAV] Block size: %u.\n", block_align); uint16_t bits_per_sample; MY_READ(file, & bits_per_sample, sizeof(bits_per_sample)); bits_per_sample = U16_TO_LE (bits_per_sample); printf("[WAV] Bits per sample: %u.\n", bits_per_sample); file_info -> bits_per_sample = bits_per_sample; uint_fast32_t oss_format; switch (bits_per_sample) { case 8: oss_format = AFMT_U8; break; case 16: oss_format = AFMT_S16_LE; break; default: fprintf(stderr, "This value of bits per sample not supported. Sorry...\n"); return 1; } file_info -> oss_format = oss_format; // Header sanity checks if (block_align != channels * bits_per_sample / 8 || (uint_fast32_t) block_align * sample_rate != byte_rate) { fprintf(stderr, "WAVE file error: Internal inconsistency in the header.\n"); return 1; } uint32_t magic_number_data; MY_READ(file, & magic_number_data, sizeof(magic_number_data)); magic_number_data = ntohl (magic_number_data); if (magic_number_data != 0x64617461) { fprintf(stderr, "WAVE file ERROR: no data.\n"); return 1; } uint32_t data_size; MY_READ(file, & data_size, sizeof(data_size)); data_size = U32_TO_LE (data_size); printf("[WAV] Data size: %u.\n",data_size); file_info -> data_size = data_size; return 0; }
/** * Read informations in AU files */ int au_opener(music_file_t * file_info) { int ret; FILE * file = file_info -> file; uint32_t header_size; MY_READ(file, & header_size, sizeof(header_size)); header_size = ntohl (header_size); printf("[AU] Header size: %u.\n", header_size); uint32_t data_size; MY_READ(file, & data_size, sizeof(data_size)); data_size = ntohl (data_size); printf("[AU] Data size: %u.\n",data_size); file_info -> data_size = data_size; uint32_t encoding; MY_READ(file, & encoding, sizeof(encoding)); encoding = ntohl (encoding); unsigned oss_format; uint_fast32_t bits_per_sample; switch (encoding) { case 2: bits_per_sample = 8; oss_format = AFMT_S8; printf("[AU] Encoding format: Signed 8-bit.\n"); break; case 3: bits_per_sample = 16; oss_format = AFMT_S16_BE; printf("[AU] Encoding format: Signed 16-bit.\n"); break; default: printf("[AU] Encoding format: %u.\n", encoding); fprintf(stderr, "Encoding not supported. Sorry...\n"); return 1; } file_info -> bits_per_sample = bits_per_sample; file_info -> oss_format = oss_format; uint32_t sample_rate; MY_READ(file, & sample_rate, sizeof(sample_rate)); sample_rate = ntohl (sample_rate); printf("[AU] Sample rate: %u.\n", sample_rate); file_info -> sample_rate = sample_rate; uint32_t channels; MY_READ(file, & channels, sizeof(channels)); channels = ntohl (channels); printf("[AU] Nb of channels: %u.\n", channels); file_info -> channels = channels; // Position the cursor to the beginning of the data section if (fseek(file, header_size, SEEK_SET) == -1) { perror("fseek"); return 2; } return 0; }