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 / wmx2.c < prev    next >
C/C++ Source or Header  |  2000-11-29  |  12KB  |  475 lines

  1. #include "quicktime.h"
  2.  
  3. static int quicktime_wmx2_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_wmx2_index[16] = 
  17. {
  18.     -1, -1, -1, -1, 2, 4, 6, 8,
  19.     -1, -1, -1, -1, 2, 4, 6, 8
  20. };
  21.  
  22. /* ================================== private for wmx2 */
  23. #define HEADER_SIZE 3
  24.  
  25. int wmx2_decode_block(quicktime_audio_map_t *atrack, QUICKTIME_INT16 *output, unsigned char *input, int samples)
  26. {
  27.     int predictor;
  28.     int index;
  29.     int step;
  30.     int i, nibble, nibble_count, block_size;
  31.     unsigned char *block_ptr;
  32.     QUICKTIME_INT16 *output_end = output + samples;
  33.     quicktime_wmx2_codec_t *codec = &(atrack->codecs.wmx2_codec);
  34.  
  35. /* Get the chunk header */
  36.     predictor = *input++ << 8;
  37.     predictor |= *input++;
  38.     if(predictor & 0x8000) predictor -= 0x10000;
  39.     index = *input++;
  40.     if(index > 88) index = 88;
  41.  
  42. /*printf("input %d %d\n", predictor, index); */
  43.     step = quicktime_wmx2_step[index];
  44.  
  45. /* Read the input buffer sequentially, one nibble at a time */
  46.     nibble_count = 0;
  47.     while(output < output_end)
  48.     {
  49.         nibble = nibble_count ? (*input++  >> 4) & 0x0f : *input & 0x0f;
  50.  
  51.         wmx2_decode_sample(&predictor, &nibble, &index, &step);
  52.         *output++ = predictor;
  53.  
  54.         nibble_count ^= 1;
  55.     }
  56. }
  57.  
  58. int wmx2_decode_sample(int *predictor, int *nibble, int *index, int *step)
  59. {
  60.     int difference, sign;
  61.  
  62. /* Get new index value */
  63.     *index += quicktime_wmx2_index[*nibble];
  64.  
  65.     if(*index < 0) *index = 0; 
  66.     else 
  67.     if(*index > 88) *index = 88;
  68.  
  69. /* Get sign and magnitude from *nibble */
  70.     sign = *nibble & 8;
  71.     *nibble = *nibble & 7;
  72.  
  73. /* Get difference */
  74.     difference = *step >> 3;
  75.     if(*nibble & 4) difference += *step;
  76.     if(*nibble & 2) difference += *step >> 1;
  77.     if(*nibble & 1) difference += *step >> 2;
  78.  
  79. /* Predict value */
  80.     if(sign) 
  81.     *predictor -= difference;
  82.     else 
  83.     *predictor += difference;
  84.  
  85.     if(*predictor > 32767) *predictor = 32767;
  86.     else
  87.     if(*predictor < -32768) *predictor = -32768;
  88.  
  89. /* Update the step value */
  90.     *step = quicktime_wmx2_step[*index];
  91.  
  92.     return 0;
  93. }
  94.  
  95.  
  96. int wmx2_encode_block(quicktime_audio_map_t *atrack, unsigned char *output, QUICKTIME_INT16 *input, int step, int channel, int samples)
  97. {
  98.     quicktime_wmx2_codec_t *codec = &(atrack->codecs.wmx2_codec);
  99.     int i, nibble_count = 0, nibble, header;
  100.  
  101. /* Get a fake starting sample */
  102.     header = codec->last_samples[channel];
  103. /*printf("output %d %d\n", header, codec->last_indexes[channel]); */
  104. /* Force rounding. */
  105. /*    if(header < 0x7fc0) header += 0x40; */
  106. /*    header &= 0xff80; */
  107.     if(header < 0) header += 0x10000;
  108.     *output++ = (header & 0xff00) >> 8;
  109.     *output++ = (header & 0xff);
  110.     *output++ = (codec->last_indexes[channel] & 0x7f);
  111.  
  112.     for(i = 0; i < samples; i++)
  113.     {
  114.         wmx2_encode_sample(&(codec->last_samples[channel]), 
  115.                             &(codec->last_indexes[channel]), 
  116.                             &nibble, 
  117.                             *input);
  118.  
  119.         if(nibble_count)
  120.             *output++ |= (nibble << 4);
  121.         else
  122.             *output = nibble;
  123.  
  124.         input += step;
  125.         nibble_count ^= 1;
  126.     }
  127.  
  128.     return 0;
  129. }
  130.  
  131. int wmx2_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
  132. {
  133.     int difference, new_difference, mask, step;
  134.  
  135.     difference = next_sample - *last_sample;
  136.     *nibble = 0;
  137.     step = quicktime_wmx2_step[*last_index];
  138.     new_difference = step >> 3;
  139.  
  140.     if(difference < 0)
  141.     {
  142.         *nibble = 8;
  143.         difference = -difference;
  144.     }
  145.  
  146.     mask = 4;
  147.     while(mask)
  148.     {
  149.         if(difference >= step)
  150.         {
  151.             *nibble |= mask;
  152.             difference -= step;
  153.             new_difference += step;
  154.         }
  155.  
  156.         step >>= 1;
  157.         mask >>= 1;
  158.     }
  159.  
  160.     if(*nibble & 8)
  161.         *last_sample -= new_difference;
  162.     else
  163.         *last_sample += new_difference;
  164.  
  165.     if(*last_sample > 32767) *last_sample = 32767;
  166.     else
  167.     if(*last_sample < -32767) *last_sample = -32767;
  168.  
  169.     *last_index += quicktime_wmx2_index[*nibble];
  170.  
  171.     if(*last_index < 0) *last_index = 0;
  172.     else
  173.     if(*last_index > 88) *last_index= 88;
  174.  
  175.     return 0;
  176. }
  177.  
  178. /* Convert the number of samples in a chunk into the number of bytes in that */
  179. /* chunk.  The number of samples in a chunk should end on a block boundary. */
  180. long wmx2_samples_to_bytes(long samples, int channels)
  181. {
  182.     long bytes = samples / 2;
  183.     if(bytes * 2 < samples) bytes++;
  184.     bytes *= channels;
  185.     bytes += HEADER_SIZE * channels;
  186.     return bytes;
  187. }
  188.  
  189. /* Decode the chunk into the work buffer */
  190. int wmx2_decode_chunk(quicktime_t *file, int track, long chunk, int channel)
  191. {
  192.     int result = 0;
  193.     int i, j;
  194.     long chunk_samples, chunk_bytes;
  195.     unsigned char *chunk_ptr, *block_ptr;
  196.     quicktime_trak_t *trak = file->atracks[track].track;
  197.     quicktime_wmx2_codec_t *codec = &(file->atracks[track].codecs.wmx2_codec);
  198.  
  199. /* Get the byte count to read. */
  200.     chunk_samples = quicktime_chunk_samples(trak, chunk);
  201.     chunk_bytes = wmx2_samples_to_bytes(chunk_samples, file->atracks[track].channels);
  202.  
  203. /* Get the buffer to read into. */
  204.     if(codec->write_buffer && codec->write_size < chunk_samples)
  205.     {
  206.         free(codec->write_buffer);
  207.         codec->write_buffer = 0;
  208.     }
  209.  
  210.     if(!codec->write_buffer)
  211.     {
  212.         codec->write_size = chunk_samples;
  213.         codec->write_buffer = malloc(sizeof(QUICKTIME_INT16) * codec->write_size);
  214.     }
  215.  
  216.     if(codec->read_buffer && codec->read_size < chunk_bytes)
  217.     {
  218.         free(codec->read_buffer);
  219.         codec->read_buffer = 0;
  220.     }
  221.  
  222.     if(!codec->read_buffer)
  223.     {
  224.         codec->read_size = chunk_bytes;
  225.         codec->read_buffer = malloc(codec->read_size);
  226.     }
  227.  
  228. /* codec->work_size now holds the number of samples in the last chunk */
  229. /* codec->read_size now holds number of bytes in the last read buffer */
  230.  
  231. /* Read the entire chunk regardless of where the desired sample range starts. */
  232.     result = quicktime_read_chunk(file, codec->read_buffer, track, chunk, 0, chunk_bytes);
  233.  
  234. /* Now decode the chunk, one block at a time, until the total samples in the chunk */
  235. /* is reached. */
  236.  
  237.     if(!result)
  238.     {
  239.         block_ptr = codec->read_buffer;
  240.         for(j = 0; j < file->atracks[track].channels; j++)
  241.         {
  242.             if(j == channel)
  243.                 wmx2_decode_block(&(file->atracks[track]), codec->write_buffer, block_ptr, chunk_samples);
  244.  
  245.             block_ptr += chunk_bytes / file->atracks[track].channels;
  246.         }
  247.     }
  248.     codec->buffer_channel = channel;
  249.     codec->chunk = chunk;
  250.  
  251.     return result;
  252. }
  253.  
  254.  
  255. /* =================================== public for wmx2 */
  256.  
  257. int quicktime_init_codec_wmx2(quicktime_audio_map_t *atrack)
  258. {
  259.     quicktime_wmx2_codec_t *codec = &(atrack->codecs.wmx2_codec);
  260.  
  261.     codec->write_buffer = 0;
  262.     codec->read_buffer = 0;
  263.     codec->chunk = 0;
  264.     codec->buffer_channel = 0;
  265.     codec->write_size = 0;
  266.     codec->read_size = 0;
  267.     codec->last_samples = 0;
  268.     codec->last_indexes = 0;
  269. /*printf("quicktime_init_codec_wmx2 1 %x %x %x\n", atrack, codec, codec->work_buffer); */
  270.     return 0;
  271. }
  272.  
  273. int quicktime_delete_codec_wmx2(quicktime_audio_map_t *atrack)
  274. {
  275.     quicktime_wmx2_codec_t *codec = &(atrack->codecs.wmx2_codec);
  276.     if(codec->write_buffer) free(codec->write_buffer);
  277.     if(codec->read_buffer) free(codec->read_buffer);
  278.     if(codec->last_samples) free(codec->last_samples);
  279.     if(codec->last_indexes) free(codec->last_indexes);
  280.     codec->last_samples = 0;
  281.     codec->last_indexes = 0;
  282.     codec->read_buffer = 0;
  283.     codec->write_buffer = 0;
  284.     codec->chunk = 0;
  285.     codec->buffer_channel = 0; /* Channel of work buffer */
  286.     codec->write_size = 0;          /* Size of work buffer */
  287.     codec->read_size = 0;
  288.     return 0;
  289. }
  290.  
  291. int quicktime_decode_wmx2(quicktime_t *file, 
  292.                     QUICKTIME_INT16 *output_i, 
  293.                     float *output_f,
  294.                     long samples, 
  295.                     int track, 
  296.                     int channel,
  297.                     int do_float)
  298. {
  299.     int result = 0;
  300.     long chunk, chunk_sample, chunk_bytes, chunk_samples;
  301.     long i, chunk_start, chunk_end;
  302.     quicktime_trak_t *trak = file->atracks[track].track;
  303.     quicktime_wmx2_codec_t *codec = &(file->atracks[track].codecs.wmx2_codec);
  304.  
  305. /* Get the first chunk with this routine and then increase the chunk number. */
  306.     quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, file->atracks[track].current_position);
  307.  
  308. /* Read chunks until the output is full. */
  309.     for(i = 0; i < samples && !result; )
  310.     {
  311. /* Get chunk we're on. */
  312.         chunk_samples = quicktime_chunk_samples(trak, chunk);
  313.  
  314.         if(!codec->write_buffer ||
  315.             codec->chunk != chunk ||
  316.             codec->buffer_channel != channel)
  317.         {
  318. /* read a new chunk if necessary */
  319.             result = wmx2_decode_chunk(file, track, chunk, channel);
  320.         }
  321.  
  322. /* Get boundaries from the chunk */
  323.         chunk_start = 0;
  324.         if(chunk_sample < file->atracks[track].current_position)
  325.             chunk_start = file->atracks[track].current_position - chunk_sample;
  326.  
  327.         chunk_end = chunk_samples;
  328.         if(chunk_sample + chunk_end > file->atracks[track].current_position + samples)
  329.             chunk_end = file->atracks[track].current_position + samples - chunk_sample;
  330.  
  331. /* Read from the chunk */
  332.         if(output_i)
  333.         {
  334.             while(chunk_start < chunk_end)
  335.             {
  336.                 output_i[i++] = codec->write_buffer[chunk_start++];
  337.             }
  338.         }
  339.         else
  340.         if(output_f)
  341.         {
  342.             while(chunk_start < chunk_end)
  343.             {
  344.                 output_f[i++] = (float)codec->write_buffer[chunk_start++] / 32767;
  345.             }
  346.         }
  347.  
  348.         chunk++;
  349.         chunk_sample += chunk_samples;
  350.     }
  351.  
  352.     return result;
  353. }
  354.  
  355. int quicktime_encode_wmx2(quicktime_t *file, 
  356.                         QUICKTIME_INT16 **input_i, 
  357.                         float **input_f, 
  358.                         int track, 
  359.                         long samples)
  360. {
  361.     int result = 0;
  362.     long i, j, step;
  363.     long chunk_bytes;
  364.     long offset;
  365.     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  366.     quicktime_wmx2_codec_t *codec = &(track_map->codecs.wmx2_codec);
  367.     QUICKTIME_INT16 *input_ptr;
  368.     unsigned char *output_ptr;
  369.  
  370. /* Get buffer sizes */
  371.     if(codec->write_buffer && codec->write_size < samples * track_map->channels)
  372.     {
  373. /* Create new buffer */
  374.         long new_size = samples * track_map->channels;
  375.         QUICKTIME_INT16 *new_buffer = malloc(sizeof(QUICKTIME_INT16) * new_size);
  376.  
  377. /* Swap pointers. */
  378.         free(codec->write_buffer);
  379.         codec->write_buffer = new_buffer;
  380.         codec->write_size = new_size;
  381.     }
  382.     else
  383.     if(!codec->write_buffer)
  384.     {
  385. /* No buffer in the first place. */
  386.         codec->write_size = samples * track_map->channels;
  387.         codec->write_buffer = malloc(sizeof(QUICKTIME_INT16) * codec->write_size);
  388.     }
  389.  
  390. /* Get output size */
  391.     chunk_bytes = wmx2_samples_to_bytes(samples, track_map->channels);
  392.     if(codec->read_buffer && codec->read_size < chunk_bytes)
  393.     {
  394.         free(codec->read_buffer);
  395.         codec->read_buffer = 0;
  396.     }
  397.  
  398.     if(!codec->read_buffer)
  399.     {
  400.         codec->read_buffer = malloc(chunk_bytes);
  401.         codec->read_size = chunk_bytes;
  402.     }
  403.  
  404.     if(!codec->last_samples)
  405.     {
  406.         codec->last_samples = malloc(sizeof(int) * track_map->channels);
  407.         for(i = 0; i < track_map->channels; i++)
  408.         {
  409.             codec->last_samples[i] = 0;
  410.         }
  411.     }
  412.  
  413.     if(!codec->last_indexes)
  414.     {
  415.         codec->last_indexes = malloc(sizeof(int) * track_map->channels);
  416.         for(i = 0; i < track_map->channels; i++)
  417.         {
  418.             codec->last_indexes[i] = 0;
  419.         }
  420.     }
  421.  
  422. /* Arm the input buffer */
  423.     step = track_map->channels;
  424.     for(j = 0; j < track_map->channels; j++)
  425.     {
  426.         input_ptr = codec->write_buffer + j;
  427.  
  428.         if(input_i)
  429.         {
  430.             for(i = 0; i < samples; i++)
  431.             {
  432.                 *input_ptr = input_i[j][i];
  433.                 input_ptr += step;
  434.             }
  435.         }
  436.         else
  437.         if(input_f)
  438.         {
  439.             for(i = 0; i < samples; i++)
  440.             {
  441.                 *input_ptr = (QUICKTIME_INT16)(input_f[j][i] * 32767);
  442.                 input_ptr += step;
  443.             }
  444.         }
  445.     }
  446.  
  447. /* Encode from the input buffer to the read_buffer. */
  448.     input_ptr = codec->write_buffer;
  449.     output_ptr = codec->read_buffer;
  450.  
  451.     for(j = 0; j < track_map->channels; j++)
  452.     {
  453.         wmx2_encode_block(track_map, output_ptr, input_ptr + j, track_map->channels, j, samples);
  454.  
  455.         output_ptr += chunk_bytes / track_map->channels;
  456.     }
  457.  
  458.     if(samples)
  459.     {
  460.         offset = quicktime_position(file);
  461.         result = quicktime_write_data(file, codec->read_buffer, chunk_bytes);
  462.         if(result) result = 0; else result = 1; /* defeat fwrite's return */
  463.         quicktime_update_tables(file,
  464.                             track_map->track, 
  465.                             offset, 
  466.                             track_map->current_chunk, 
  467.                             track_map->current_position, 
  468.                             samples, 
  469.                             0);
  470.         file->atracks[track].current_chunk++;
  471.     }
  472.  
  473.     return result;
  474. }
  475.