long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { quicktime_audio_map_t *track_map = &file->atracks[track]; quicktime_trak_t *trak = track_map->track; int64_t position, chunk, chunk_sample; long ret, bytes, chunk_offset, chunk_len; int result = 0; position = file->atracks[track].current_position; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); ret = 0; while( samples > 0 ) { int64_t offset = quicktime_sample_to_offset(file, trak, position); quicktime_set_position(file, offset); chunk_offset = position - chunk_sample; chunk_len = quicktime_chunk_samples(trak, chunk) - chunk_offset; if( chunk_len > samples ) chunk_len = samples; else ++chunk; chunk_sample = (position += chunk_len); bytes = quicktime_samples_to_bytes(trak, chunk_len); result = !quicktime_read_data(file, &audio_buffer[ret], bytes); if( result ) break; ret += bytes; samples -= chunk_len; } //printf("quicktime_read_audio 5\n"); track_map->current_position = position; track_map->current_chunk = chunk; return !result ? ret : 0; }
long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { int64_t chunk_sample, chunk; int result = 0, track_num; quicktime_trak_t *trak = file->atracks[track].track; int64_t fragment_len, chunk_end; int64_t start_position = file->atracks[track].current_position; int64_t position = file->atracks[track].current_position; int64_t start = position, end = position + samples; int64_t bytes, total_bytes = 0; int64_t buffer_offset; //printf("quicktime_read_audio 1\n"); quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); buffer_offset = 0; while(position < end && !result) { quicktime_set_audio_position(file, position, track); fragment_len = quicktime_chunk_samples(trak, chunk); chunk_end = chunk_sample + fragment_len; fragment_len -= position - chunk_sample; if(position + fragment_len > chunk_end) fragment_len = chunk_end - position; if(position + fragment_len > end) fragment_len = end - position; bytes = quicktime_samples_to_bytes(trak, fragment_len); /* * printf("quicktime_read_audio 2 %llx %llx %d\n", * quicktime_position(file), * quicktime_position(file) + bytes, * samples); * sleep(1); */ result = !quicktime_read_data(file, &audio_buffer[buffer_offset], bytes); //printf("quicktime_read_audio 4\n"); total_bytes += bytes; position += fragment_len; chunk_sample = position; buffer_offset += bytes; chunk++; } //printf("quicktime_read_audio 5\n"); // Create illusion of track being advanced only by samples file->atracks[track].current_position = start_position + samples; if(result) return 0; return total_bytes; }
long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { long chunk_sample, chunk; int result = 1, track_num; quicktime_trak_t *trak = file->atracks[track].track; long fragment_len, chunk_end; long position = file->atracks[track].current_position; long start = position, end = position + samples; long bytes, total_bytes = 0; long buffer_offset; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); buffer_offset = 0; while(position < end && result) { quicktime_set_audio_position(file, position, track); fragment_len = quicktime_chunk_samples(trak, chunk); chunk_end = chunk_sample + fragment_len; fragment_len -= position - chunk_sample; if(position + fragment_len > chunk_end) fragment_len = chunk_end - position; if(position + fragment_len > end) fragment_len = end - position; bytes = quicktime_samples_to_bytes(trak, fragment_len); result = quicktime_read_data(file, &audio_buffer[buffer_offset], bytes); total_bytes += bytes; position += fragment_len; chunk_sample = position; buffer_offset += bytes; chunk++; } file->atracks[track].current_position = position; if(!result) return 0; return total_bytes; }
static int decode(quicktime_t *file, int16_t *output_i, float *output_f, long samples, int track, int channel) { int result = 0; int64_t chunk, chunk_sample, chunk_samples; int64_t i, chunk_start, chunk_end; quicktime_trak_t *trak = file->atracks[track].track; quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv; /* Get the first chunk with this routine and then increase the chunk number. */ quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, file->atracks[track].current_position); /* Read chunks and extract ranges of samples until the output is full. */ for(i = 0; i < samples && !result; ) { /* Get chunk we're on. */ chunk_samples = quicktime_chunk_samples(trak, chunk); if(!codec->work_buffer || codec->chunk != chunk || codec->buffer_channel != channel) { /* read a new chunk if necessary */ result = ima4_decode_chunk(file, track, chunk, channel); } /* Get boundaries from the chunk */ chunk_start = 0; if(chunk_sample < file->atracks[track].current_position) chunk_start = file->atracks[track].current_position - chunk_sample; chunk_end = chunk_samples; if(chunk_sample + chunk_end > file->atracks[track].current_position + samples) chunk_end = file->atracks[track].current_position + samples - chunk_sample; /* Read from the chunk */ if(output_i) { /*printf("decode_ima4 1 chunk %ld %ld-%ld output %ld\n", chunk, chunk_start + chunk_sample, chunk_end + chunk_sample, i); */ while(chunk_start < chunk_end) { output_i[i++] = codec->work_buffer[chunk_start++]; } /*printf("decode_ima4 2\n"); */ } else if(output_f) { while(chunk_start < chunk_end) { output_f[i++] = (float)codec->work_buffer[chunk_start++] / 32767; } } chunk++; chunk_sample += chunk_samples; } return result; }
/* Decode the chunk into the work buffer */ int ima4_decode_chunk(quicktime_t *file, int track, long chunk, int channel) { int result = 0; int i, j; long chunk_samples, chunk_bytes; unsigned char *block_ptr; quicktime_trak_t *trak = file->atracks[track].track; quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv; /* Get the byte count to read. */ chunk_samples = quicktime_chunk_samples(trak, chunk); chunk_bytes = ima4_samples_to_bytes(chunk_samples, file->atracks[track].channels); /* Get the buffer to read into. */ if(codec->work_buffer && codec->work_size < chunk_samples) { free(codec->work_buffer); codec->work_buffer = 0; } if(!codec->work_buffer) { codec->work_size = chunk_samples; codec->work_buffer = malloc(sizeof(int16_t) * codec->work_size); } if(codec->read_buffer && codec->read_size < chunk_bytes) { free(codec->read_buffer); codec->read_buffer = 0; } if(!codec->read_buffer) { codec->read_size = chunk_bytes; codec->read_buffer = malloc(codec->read_size); } /* codec->work_size now holds the number of samples in the last chunk */ /* codec->read_size now holds number of bytes in the last read buffer */ /* Read the entire chunk regardless of where the desired sample range starts. */ result = quicktime_read_chunk(file, (char*)codec->read_buffer, track, chunk, 0, chunk_bytes); /* Now decode the chunk, one block at a time, until the total samples in the chunk */ /* is reached. */ if(!result) { block_ptr = codec->read_buffer; for(i = 0; i < chunk_samples; i += SAMPLES_PER_BLOCK) { for(j = 0; j < file->atracks[track].channels; j++) { if(j == channel) ima4_decode_block(&(file->atracks[track]), &(codec->work_buffer[i]), block_ptr); block_ptr += BLOCK_SIZE; } } } codec->buffer_channel = channel; codec->chunk = chunk; return result; }