home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / quicktime / ima4.c < prev    next >
C/C++ Source or Header  |  2000-11-29  |  15KB  |  541 lines

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