initial commit
[goodguy/history.git] / cinelerra-5.0 / quicktime / rawaudio.c
1 #include "quicktime.h"
2 #include "rawaudio.h"
3 #include <math.h>
4
5 typedef struct
6 {
7         char *work_buffer;
8         long buffer_size;
9 } quicktime_rawaudio_codec_t;
10
11 /* =================================== private for rawaudio */
12
13 static int is_little_endian(void)
14 {
15         int16_t test = 0x0001;
16         return *((unsigned char *)&test);
17 }
18
19 static int get_work_buffer(quicktime_t *file, int track, long bytes)
20 {
21         quicktime_rawaudio_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv;
22
23         if(codec->work_buffer && codec->buffer_size != bytes) {
24                 free(codec->work_buffer);
25                 codec->work_buffer = 0;
26         }
27         
28         if(!codec->work_buffer) {
29                 codec->buffer_size = bytes;
30                 if(!(codec->work_buffer = malloc(bytes))) return 1;
31         }
32         return 0;
33 }
34
35 /* =================================== public for rawaudio */
36
37 static void quicktime_delete_codec_rawaudio(quicktime_audio_map_t *atrack)
38 {
39         quicktime_rawaudio_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
40
41         if(codec->work_buffer) free(codec->work_buffer);
42         codec->work_buffer = 0;
43         codec->buffer_size = 0;
44         free(codec);
45 }
46
47 static int fclip(float f, int mx)
48 {
49   f *= mx;  f += f >= 0 ? 0.5f : -0.5f;
50   return f >= mx ? mx+mx-1 : f < -mx ? 0 : (int)f + mx;
51 }
52 static int fclip8 (float f) { return fclip(f,0x80); }
53 static int fclip16(float f) { return fclip(f,0x8000); }
54 static int fclip24(float f) { return fclip(f,0x800000); }
55
56 static int   rd8be_s16 (uint8_t *bp) { return (bp[0]<<8) - 0x8000; }
57 static int   rd8le_s16 (uint8_t *bp) { return (bp[0]<<8) - 0x8000; }
58 static int   rd16be_s16(uint8_t *bp) { return ((bp[0]<<8) | bp[1]) - 0x8000; }
59 static int   rd16le_s16(uint8_t *bp) { return (bp[0] | (bp[1]<<8)) - 0x8000; }
60 static int   rd24be_s16(uint8_t *bp) { return ((bp[0]<<8) | bp[1]) - 0x8000; }
61 static int   rd24le_s16(uint8_t *bp) { return (bp[1] | (bp[2]<<8)) - 0x8000; }
62 static float rd8be_flt (uint8_t *bp) { return (float)(bp[0]-0x80)/0x80; }
63 static float rd8le_flt (uint8_t *bp) { return (float)(bp[0]-0x80)/0x80; }
64 static float rd16be_flt(uint8_t *bp) { return (float)(((bp[0]<<8) | bp[1])-0x8000)/0x8000; }
65 static float rd16le_flt(uint8_t *bp) { return (float)((bp[0] | (bp[1]<<8))-0x8000)/0x8000; }
66 static float rd24be_flt(uint8_t *bp) { return (float)(((bp[0]<<16) | (bp[1]<<8) | bp[2])-0x800000)/0x800000; }
67 static float rd24le_flt(uint8_t *bp) { return (float)((bp[0] | (bp[1]<<8) | (bp[2]<<16))-0x800000)/0x800000; }
68
69 static void wr8be_s16 (uint8_t *bp, int v)   { v+=0x8000; bp[0] = v>>8; }
70 static void wr8le_s16 (uint8_t *bp, int v)   { v+=0x8000; bp[0] = v>>8; }
71 static void wr16be_s16(uint8_t *bp, int v)   { v+=0x8000; bp[0] = v>>8; bp[1] = v; }
72 static void wr16le_s16(uint8_t *bp, int v)   { v+=0x8000; bp[0] = v; bp[1] = v>>8; }
73 static void wr24be_s16(uint8_t *bp, int v)   { v+=0x8000; bp[0] = v>>8; bp[1] = v; bp[2] = 0; }
74 static void wr24le_s16(uint8_t *bp, int v)   { v+=0x8000; bp[0] = 0; bp[1] = v; bp[2] = v>>8; }
75 static void wr8be_flt (uint8_t *bp, float f) { int v = fclip8(f); bp[0] = v; }
76 static void wr8le_flt (uint8_t *bp, float f) { int v = fclip8(f); bp[0] = v; }
77 static void wr16be_flt(uint8_t *bp, float f) { int v = fclip16(f); bp[0] = v>>8; bp[1] = v; }
78 static void wr16le_flt(uint8_t *bp, float f) { int v = fclip16(f); bp[0] = v; bp[1] = v>>8; }
79 static void wr24be_flt(uint8_t *bp, float f) { int v = fclip24(f); bp[0] = v>>16; bp[1] = v>>8; bp[2] = v; }
80 static void wr24le_flt(uint8_t *bp, float f) { int v = fclip24(f); bp[0] = v; bp[1] = v>>8; bp[2] = v>>16; }
81
82 #define rd_samples(typ, fn, out, step) { \
83   uint8_t *bp = (uint8_t *)codec->work_buffer + channel*byts; \
84   for( i=0; i<samples; ++i ) { *out++ = fn(bp); bp += step; } \
85 }
86
87 #define wr_samples(typ, fn, in, step) { \
88   for( j=0; j<channels; ++j ) { typ *inp = in[j]; \
89     uint8_t *bp = (uint8_t *)codec->work_buffer + j*byts; \
90     for( i=0; i<samples; ++i ) { fn(bp,*inp++); bp += step; } \
91   } \
92 }
93
94 static int quicktime_decode_rawaudio(quicktime_t *file, 
95                 int16_t *output_i, float *output_f, long samples, 
96                 int track, int channel)
97 {
98         int i, result;
99         int little_endian = is_little_endian();
100         quicktime_audio_map_t *track_map = &(file->atracks[track]);
101         quicktime_rawaudio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
102         int bits = quicktime_audio_bits(file, track);
103         int byts = bits/8, channels = file->atracks[track].channels;
104         int size = channels * byts;
105         get_work_buffer(file, track, samples * size);
106         result = !quicktime_read_audio(file, codec->work_buffer, samples, track);
107         if( result ) return result;
108 // Undo increment since this is done in codecs.c
109         track_map->current_position -= samples;
110         if( !little_endian ) {
111                 if( output_i ) {
112                         switch( byts ) {
113                         case 1:  rd_samples(int16_t,rd8be_s16,output_i,size);   break;
114                         case 2:  rd_samples(int16_t,rd16be_s16,output_i,size);  break;
115                         case 3:  rd_samples(int16_t,rd24be_s16,output_i,size);  break;
116                         }
117                 }
118                 else if( output_f ) {
119                         switch( byts ) {
120                         case 1:  rd_samples(float,rd8be_flt,output_f,size);   break;
121                         case 2:  rd_samples(float,rd16be_flt,output_f,size);  break;
122                         case 3:  rd_samples(float,rd24be_flt,output_f,size);  break;
123                         }
124                 }
125         }
126         else {
127 // Undo increment since this is done in codecs.c
128                 track_map->current_position -= samples;
129                 if( output_i ) {
130                         switch( byts ) {
131                         case 1:  rd_samples(int16_t,rd8le_s16,output_i,size);   break;
132                         case 2:  rd_samples(int16_t,rd16le_s16,output_i,size);  break;
133                         case 3:  rd_samples(int16_t,rd24le_s16,output_i,size);  break;
134                         }
135                 }
136                 else if( output_f ) {
137                         switch( byts ) {
138                         case 1:  rd_samples(float,rd8le_flt,output_f,size);   break;
139                         case 2:  rd_samples(float,rd16le_flt,output_f,size);  break;
140                         case 3:  rd_samples(float,rd24le_flt,output_f,size);  break;
141                         }
142                 }
143         }
144 /*printf("quicktime_decode_rawaudio 2\n"); */
145         return 0;
146 }
147
148 static int quicktime_encode_rawaudio(quicktime_t *file, 
149                 int16_t **input_i, float **input_f, int track, long samples)
150 {
151         int i, j, result;
152         int little_endian = is_little_endian();
153         quicktime_audio_map_t *track_map = &(file->atracks[track]);
154         quicktime_rawaudio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
155         int bits = quicktime_audio_bits(file, track);
156         int byts = bits/8, channels = file->atracks[track].channels;
157         int size = channels * byts;
158         get_work_buffer(file, track, samples * size);
159
160         if( !little_endian ) {
161                 if( input_i ) {
162                         switch( byts ) {
163                         case 1:  wr_samples(int16_t,wr8be_s16,input_i,size);   break;
164                         case 2:  wr_samples(int16_t,wr16be_s16,input_i,size);  break;
165                         case 3:  wr_samples(int16_t,wr24be_s16,input_i,size);  break;
166                         }
167                 }
168                 else if( input_f ) {
169                         switch( byts ) {
170                         case 1:  wr_samples(float,wr8be_flt,input_f,size);   break;
171                         case 2:  wr_samples(float,wr16be_flt,input_f,size);  break;
172                         case 3:  wr_samples(float,wr24be_flt,input_f,size);  break;
173                         }
174                 }
175         }
176         else {
177                 if( input_i ) {
178                         switch( byts ) {
179                         case 1:  wr_samples(int16_t,wr8le_s16,input_i,size);   break;
180                         case 2:  wr_samples(int16_t,wr16le_s16,input_i,size);  break;
181                         case 3:  wr_samples(int16_t,wr24le_s16,input_i,size);  break;
182                         }
183                 }
184                 else if( input_f ) {
185                         switch( byts ) {
186                         case 1:  wr_samples(float,wr8le_flt,input_f,size);   break;
187                         case 2:  wr_samples(float,wr16le_flt,input_f,size);  break;
188                         case 3:  wr_samples(float,wr24le_flt,input_f,size);  break;
189                         }
190                 }
191         }
192
193         result = quicktime_write_audio(file, (char *)codec->work_buffer, samples, track);
194         return result;
195 }
196
197
198 void quicktime_init_codec_rawaudio(quicktime_audio_map_t *atrack)
199 {
200         quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
201 //      quicktime_rawaudio_codec_t *codec = codec_base->priv;
202
203 /* Init public items */
204         codec_base->priv = calloc(1, sizeof(quicktime_rawaudio_codec_t));
205         codec_base->delete_acodec = quicktime_delete_codec_rawaudio;
206         codec_base->decode_video = 0;
207         codec_base->encode_video = 0;
208         codec_base->decode_audio = quicktime_decode_rawaudio;
209         codec_base->encode_audio = quicktime_encode_rawaudio;
210         codec_base->fourcc = QUICKTIME_RAW;
211         codec_base->title = "8 bit unsigned";
212         codec_base->desc = "8 bit unsigned for audio";
213         codec_base->wav_id = 0x01;
214 /* Init private items */
215 }