"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/ima4.c" (9 Jan 2007, 15062 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "funcprotos.h"
    2 #include "ima4.h"
    3 #include "quicktime.h"
    4 
    5 typedef struct
    6 {
    7 /* During decoding the work_buffer contains the most recently read chunk. */
    8 /* During encoding the work_buffer contains interlaced overflow samples  */
    9 /* from the last chunk written. */
   10     int16_t *work_buffer;
   11     unsigned char *read_buffer;    /* Temporary buffer for drive reads. */
   12 
   13 /* Starting information for all channels during encoding. */
   14     int *last_samples, *last_indexes;
   15     long chunk; /* Number of chunk in work buffer */
   16     int buffer_channel; /* Channel of work buffer */
   17 
   18 /* Number of samples in largest chunk read. */
   19 /* Number of samples plus overflow in largest chunk write, interlaced. */
   20     long work_size;     
   21     long work_overflow; /* Number of overflow samples from the last chunk written. */
   22     long read_size;     /* Size of read buffer. */
   23 } quicktime_ima4_codec_t;
   24 
   25 static int ima4_step[89] = 
   26 {
   27     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
   28     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
   29     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
   30     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
   31     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
   32     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
   33     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
   34     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
   35     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
   36 };
   37 
   38 static int ima4_index[16] = 
   39 {
   40     -1, -1, -1, -1, 2, 4, 6, 8,
   41     -1, -1, -1, -1, 2, 4, 6, 8
   42 };
   43 
   44 /* Known by divine revelation */
   45 
   46 #define BLOCK_SIZE 0x22
   47 #define SAMPLES_PER_BLOCK 0x40
   48 
   49 /* ================================== private for ima4 */
   50 
   51 
   52 void ima4_decode_sample(int *predictor, int *nibble, int *index, int *step)
   53 {
   54     int difference, sign;
   55 
   56 /* Get new index value */
   57     *index += ima4_index[*nibble];
   58 
   59     if(*index < 0) *index = 0; 
   60     else 
   61     if(*index > 88) *index = 88;
   62 
   63 /* Get sign and magnitude from *nibble */
   64     sign = *nibble & 8;
   65     *nibble = *nibble & 7;
   66 
   67 /* Get difference */
   68     difference = *step >> 3;
   69     if(*nibble & 4) difference += *step;
   70     if(*nibble & 2) difference += *step >> 1;
   71     if(*nibble & 1) difference += *step >> 2;
   72 
   73 /* Predict value */
   74     if(sign) 
   75     *predictor -= difference;
   76     else 
   77     *predictor += difference;
   78 
   79     if(*predictor > 32767) *predictor = 32767;
   80     else
   81     if(*predictor < -32768) *predictor = -32768;
   82 
   83 /* Update the step value */
   84     *step = ima4_step[*index];
   85 }
   86 
   87 void ima4_decode_block(quicktime_audio_map_t *atrack, int16_t *output, unsigned char *input)
   88 {
   89     int predictor;
   90     int index;
   91     int step;
   92     int i, nibble, nibble_count, block_size;
   93     unsigned char *block_ptr;
   94     unsigned char *input_end = input + BLOCK_SIZE;
   95     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
   96 
   97 /* Get the chunk header */
   98     predictor = *input++ << 8;
   99     predictor |= *input++;
  100 
  101     index = predictor & 0x7f;
  102     if(index > 88) index = 88;
  103 
  104     predictor &= 0xff80;
  105     if(predictor & 0x8000) predictor -= 0x10000;
  106     step = ima4_step[index];
  107 
  108 /* Read the input buffer sequentially, one nibble at a time */
  109     nibble_count = 0;
  110     while(input < input_end)
  111     {
  112         nibble = nibble_count ? (*input++  >> 4) & 0x0f : *input & 0x0f;
  113 
  114         ima4_decode_sample(&predictor, &nibble, &index, &step);
  115         *output++ = predictor;
  116 
  117         nibble_count ^= 1;
  118     }
  119 }
  120 
  121 
  122 void ima4_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
  123 {
  124     int difference, new_difference, mask, step;
  125 
  126     difference = next_sample - *last_sample;
  127     *nibble = 0;
  128     step = ima4_step[*last_index];
  129     new_difference = step >> 3;
  130 
  131     if(difference < 0)
  132     {
  133         *nibble = 8;
  134         difference = -difference;
  135     }
  136 
  137     mask = 4;
  138     while(mask)
  139     {
  140         if(difference >= step)
  141         {
  142             *nibble |= mask;
  143             difference -= step;
  144             new_difference += step;
  145         }
  146 
  147         step >>= 1;
  148         mask >>= 1;
  149     }
  150 
  151     if(*nibble & 8)
  152         *last_sample -= new_difference;
  153     else
  154         *last_sample += new_difference;
  155 
  156     if(*last_sample > 32767) *last_sample = 32767;
  157     else
  158     if(*last_sample < -32767) *last_sample = -32767;
  159 
  160     *last_index += ima4_index[*nibble];
  161 
  162     if(*last_index < 0) *last_index = 0;
  163     else
  164     if(*last_index > 88) *last_index= 88;
  165 }
  166 
  167 void ima4_encode_block(quicktime_audio_map_t *atrack, unsigned char *output, int16_t *input, int step, int channel)
  168 {
  169     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
  170     int i, nibble_count = 0, nibble, header;
  171 
  172 /* Get a fake starting sample */
  173     header = codec->last_samples[channel];
  174 /* Force rounding. */
  175     if(header < 0x7fc0) header += 0x40;
  176     if(header < 0) header += 0x10000;
  177     header &= 0xff80;
  178     *output++ = (header & 0xff00) >> 8;
  179     *output++ = (header & 0x80) + (codec->last_indexes[channel] & 0x7f);
  180 
  181     for(i = 0; i < SAMPLES_PER_BLOCK; i++)
  182     {
  183         ima4_encode_sample(&(codec->last_samples[channel]), 
  184                             &(codec->last_indexes[channel]), 
  185                             &nibble, 
  186                             *input);
  187 
  188         if(nibble_count)
  189             *output++ |= (nibble << 4);
  190         else
  191             *output = nibble;
  192 
  193         input += step;
  194         nibble_count ^= 1;
  195     }
  196 }
  197 
  198 /* Convert the number of samples in a chunk into the number of bytes in that */
  199 /* chunk.  The number of samples in a chunk should end on a block boundary. */
  200 long ima4_samples_to_bytes(long samples, int channels)
  201 {
  202     long bytes = samples / SAMPLES_PER_BLOCK * BLOCK_SIZE * channels;
  203     return bytes;
  204 }
  205 
  206 /* Decode the chunk into the work buffer */
  207 int ima4_decode_chunk(quicktime_t *file, int track, long chunk, int channel)
  208 {
  209     int result = 0;
  210     int i, j;
  211     long chunk_samples, chunk_bytes;
  212     unsigned char *chunk_ptr, *block_ptr;
  213     quicktime_trak_t *trak = file->atracks[track].track;
  214     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv;
  215 
  216 /* Get the byte count to read. */
  217     chunk_samples = quicktime_chunk_samples(trak, chunk);
  218     chunk_bytes = ima4_samples_to_bytes(chunk_samples, file->atracks[track].channels);
  219 
  220 /* Get the buffer to read into. */
  221     if(codec->work_buffer && codec->work_size < chunk_samples)
  222     {
  223         free(codec->work_buffer);
  224         codec->work_buffer = 0;
  225     }
  226 
  227     if(!codec->work_buffer)
  228     {
  229         codec->work_size = chunk_samples;
  230         codec->work_buffer = malloc(sizeof(int16_t) * codec->work_size);
  231     }
  232 
  233     if(codec->read_buffer && codec->read_size < chunk_bytes)
  234     {
  235         free(codec->read_buffer);
  236         codec->read_buffer = 0;
  237     }
  238 
  239     if(!codec->read_buffer)
  240     {
  241         codec->read_size = chunk_bytes;
  242         codec->read_buffer = malloc(codec->read_size);
  243     }
  244 
  245 /* codec->work_size now holds the number of samples in the last chunk */
  246 /* codec->read_size now holds number of bytes in the last read buffer */
  247 
  248 /* Read the entire chunk regardless of where the desired sample range starts. */
  249     result = quicktime_read_chunk(file, codec->read_buffer, track, chunk, 0, chunk_bytes);
  250 
  251 /* Now decode the chunk, one block at a time, until the total samples in the chunk */
  252 /* is reached. */
  253 
  254     if(!result)
  255     {
  256         block_ptr = codec->read_buffer;
  257         for(i = 0; i < chunk_samples; i += SAMPLES_PER_BLOCK)
  258         {
  259             for(j = 0; j < file->atracks[track].channels; j++)
  260             {
  261                 if(j == channel)
  262                     ima4_decode_block(&(file->atracks[track]), &(codec->work_buffer[i]), block_ptr);
  263 
  264                 block_ptr += BLOCK_SIZE;
  265             }
  266         }
  267     }
  268     codec->buffer_channel = channel;
  269     codec->chunk = chunk;
  270 
  271     return result;
  272 }
  273 
  274 
  275 /* =================================== public for ima4 */
  276 
  277 static int delete_codec(quicktime_audio_map_t *atrack)
  278 {
  279     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
  280 
  281     if(codec->work_buffer) free(codec->work_buffer);
  282     if(codec->read_buffer) free(codec->read_buffer);
  283     if(codec->last_samples) free(codec->last_samples);
  284     if(codec->last_indexes) free(codec->last_indexes);
  285     codec->last_samples = 0;
  286     codec->last_indexes = 0;
  287     codec->read_buffer = 0;
  288     codec->work_buffer = 0;
  289     codec->chunk = 0;
  290     codec->buffer_channel = 0; /* Channel of work buffer */
  291     codec->work_size = 0;          /* Size of work buffer */
  292     codec->read_size = 0;
  293     free(codec);
  294     return 0;
  295 }
  296 
  297 static int decode(quicktime_t *file, 
  298                     int16_t *output_i, 
  299                     float *output_f,
  300                     long samples, 
  301                     int track, 
  302                     int channel)
  303 {
  304     int result = 0;
  305     int64_t chunk, chunk_sample, chunk_bytes, chunk_samples;
  306     int64_t i, chunk_start, chunk_end;
  307     quicktime_trak_t *trak = file->atracks[track].track;
  308     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv;
  309 
  310 /* Get the first chunk with this routine and then increase the chunk number. */
  311     quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, file->atracks[track].current_position);
  312 
  313 /* Read chunks and extract ranges of samples until the output is full. */
  314     for(i = 0; i < samples && !result; )
  315     {
  316 /* Get chunk we're on. */
  317         chunk_samples = quicktime_chunk_samples(trak, chunk);
  318 
  319         if(!codec->work_buffer ||
  320             codec->chunk != chunk ||
  321             codec->buffer_channel != channel)
  322         {
  323 /* read a new chunk if necessary */
  324             result = ima4_decode_chunk(file, track, chunk, channel);
  325         }
  326 
  327 /* Get boundaries from the chunk */
  328         chunk_start = 0;
  329         if(chunk_sample < file->atracks[track].current_position)
  330             chunk_start = file->atracks[track].current_position - chunk_sample;
  331 
  332         chunk_end = chunk_samples;
  333         if(chunk_sample + chunk_end > file->atracks[track].current_position + samples)
  334             chunk_end = file->atracks[track].current_position + samples - chunk_sample;
  335 
  336 /* Read from the chunk */
  337         if(output_i)
  338         {
  339 /*printf("decode_ima4 1 chunk %ld %ld-%ld output %ld\n", chunk, chunk_start + chunk_sample, chunk_end + chunk_sample, i); */
  340             while(chunk_start < chunk_end)
  341             {
  342                 output_i[i++] = codec->work_buffer[chunk_start++];
  343             }
  344 /*printf("decode_ima4 2\n"); */
  345         }
  346         else
  347         if(output_f)
  348         {
  349             while(chunk_start < chunk_end)
  350             {
  351                 output_f[i++] = (float)codec->work_buffer[chunk_start++] / 32767;
  352             }
  353         }
  354 
  355         chunk++;
  356         chunk_sample += chunk_samples;
  357     }
  358 
  359     return result;
  360 }
  361 
  362 static int encode(quicktime_t *file, 
  363                         int16_t **input_i, 
  364                         float **input_f, 
  365                         int track, 
  366                         long samples)
  367 {
  368     int result = 0;
  369     int64_t i, j, step;
  370     int64_t chunk_bytes;
  371     int64_t overflow_start;
  372     int64_t offset;
  373     int64_t chunk_samples; /* Samples in the current chunk to be written */
  374     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  375     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
  376     quicktime_trak_t *trak = track_map->track;
  377     int16_t *input_ptr;
  378     unsigned char *output_ptr;
  379     quicktime_atom_t chunk_atom;
  380 
  381 /* Get buffer sizes */
  382     if(codec->work_buffer && codec->work_size < (samples + codec->work_overflow + 1) * track_map->channels)
  383     {
  384 /* Create new buffer */
  385         int64_t new_size = (samples + codec->work_overflow + 1) * track_map->channels;
  386         int16_t *new_buffer = malloc(sizeof(int16_t) * new_size);
  387 
  388 /* Copy overflow */
  389         for(i = 0; i < codec->work_overflow * track_map->channels; i++)
  390             new_buffer[i] = codec->work_buffer[i];
  391 
  392 /* Swap pointers. */
  393         free(codec->work_buffer);
  394         codec->work_buffer = new_buffer;
  395         codec->work_size = new_size;
  396     }
  397     else
  398     if(!codec->work_buffer)
  399     {
  400 /* No buffer in the first place. */
  401         codec->work_size = (samples + codec->work_overflow) * track_map->channels;
  402 /* Make the allocation enough for at least the flush routine. */
  403         if(codec->work_size < SAMPLES_PER_BLOCK * track_map->channels)
  404             codec->work_size = SAMPLES_PER_BLOCK * track_map->channels;
  405         codec->work_buffer = malloc(sizeof(int16_t) * codec->work_size);
  406     }
  407 
  408 /* Get output size */
  409     chunk_bytes = ima4_samples_to_bytes(samples + codec->work_overflow, track_map->channels);
  410     if(codec->read_buffer && codec->read_size < chunk_bytes)
  411     {
  412         free(codec->read_buffer);
  413         codec->read_buffer = 0;
  414     }
  415 
  416     if(!codec->read_buffer)
  417     {
  418         codec->read_buffer = malloc(chunk_bytes);
  419         codec->read_size = chunk_bytes;
  420     }
  421 
  422     if(!codec->last_samples)
  423     {
  424         codec->last_samples = malloc(sizeof(int) * track_map->channels);
  425         for(i = 0; i < track_map->channels; i++)
  426         {
  427             codec->last_samples[i] = 0;
  428         }
  429     }
  430 
  431     if(!codec->last_indexes)
  432     {
  433         codec->last_indexes = malloc(sizeof(int) * track_map->channels);
  434         for(i = 0; i < track_map->channels; i++)
  435         {
  436             codec->last_indexes[i] = 0;
  437         }
  438     }
  439 
  440 /* Arm the input buffer after the last overflow */
  441     step = track_map->channels;
  442     for(j = 0; j < track_map->channels; j++)
  443     {
  444         input_ptr = codec->work_buffer + codec->work_overflow * track_map->channels + j;
  445 
  446         if(input_i)
  447         {
  448             for(i = 0; i < samples; i++)
  449             {
  450                 *input_ptr = input_i[j][i];
  451                 input_ptr += step;
  452             }
  453         }
  454         else
  455         if(input_f)
  456         {
  457             for(i = 0; i < samples; i++)
  458             {
  459                 *input_ptr = (int16_t)(input_f[j][i] * 32767);
  460                 input_ptr += step;
  461             }
  462         }
  463     }
  464 
  465 /* Encode from the input buffer to the read_buffer up to a multiple of  */
  466 /* blocks. */
  467     input_ptr = codec->work_buffer;
  468     output_ptr = codec->read_buffer;
  469 
  470     for(i = 0; 
  471         i + SAMPLES_PER_BLOCK <= samples + codec->work_overflow; 
  472         i += SAMPLES_PER_BLOCK)
  473     {
  474         for(j = 0; j < track_map->channels; j++)
  475         {
  476             ima4_encode_block(track_map, output_ptr, input_ptr + j, track_map->channels, j);
  477 
  478             output_ptr += BLOCK_SIZE;
  479         }
  480         input_ptr += SAMPLES_PER_BLOCK * track_map->channels;
  481     }
  482 
  483 /* Write to disk */
  484     chunk_samples = (int64_t)((samples + codec->work_overflow) / SAMPLES_PER_BLOCK) * SAMPLES_PER_BLOCK;
  485 
  486 /*printf("quicktime_encode_ima4 1 %ld\n", chunk_samples); */
  487 /* The block division may result in 0 samples getting encoded. */
  488 /* Don't write 0 samples. */
  489     if(chunk_samples)
  490     {
  491         quicktime_write_chunk_header(file, trak, &chunk_atom);
  492         result = quicktime_write_data(file, codec->read_buffer, chunk_bytes);
  493         quicktime_write_chunk_footer(file, 
  494             trak,
  495             track_map->current_chunk,
  496             &chunk_atom, 
  497             chunk_samples);
  498 
  499         if(result) 
  500             result = 0; 
  501         else 
  502             result = 1; /* defeat fwrite's return */
  503 
  504         track_map->current_chunk++;
  505     }
  506 
  507 /* Move the last overflow to the front */
  508     overflow_start = i;
  509     input_ptr = codec->work_buffer;
  510     for(i = overflow_start * track_map->channels ; 
  511         i < (samples + codec->work_overflow) * track_map->channels; 
  512         i++)
  513     {
  514         *input_ptr++ = codec->work_buffer[i];
  515     }
  516     codec->work_overflow = samples + codec->work_overflow - overflow_start;
  517 
  518     return result;
  519 }
  520 
  521 void flush(quicktime_t *file, int track)
  522 {
  523     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  524     quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
  525     int result = 0;
  526     int i;
  527 
  528 /*printf("quicktime_flush_ima4 %ld\n", codec->work_overflow); */
  529     if(codec->work_overflow)
  530     {
  531 /* Zero out enough to get a block */
  532         i = codec->work_overflow * track_map->channels;
  533         while(i < SAMPLES_PER_BLOCK * track_map->channels)
  534         {
  535             codec->work_buffer[i++] = 0;
  536         }
  537         codec->work_overflow = i / track_map->channels + 1;
  538 /* Write the work_overflow only. */
  539         result = encode(file, 0, 0, track, 0);
  540     }
  541 }
  542 
  543 void quicktime_init_codec_ima4(quicktime_audio_map_t *atrack)
  544 {
  545     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  546     quicktime_ima4_codec_t *codec;
  547 
  548 /* Init public items */
  549     codec_base->priv = calloc(1, sizeof(quicktime_ima4_codec_t));
  550     codec_base->delete_acodec = delete_codec;
  551     codec_base->decode_video = 0;
  552     codec_base->encode_video = 0;
  553     codec_base->decode_audio = decode;
  554     codec_base->encode_audio = encode;
  555     codec_base->flush = flush;
  556     codec_base->fourcc = QUICKTIME_IMA4;
  557     codec_base->title = "IMA 4";
  558     codec_base->desc = "IMA 4";
  559     codec_base->wav_id = 0x11;
  560 
  561 /* Init private items */
  562     codec = codec_base->priv;
  563 }