3396
|
1 // liba52 sample by A'rpi/ESP-team
|
25479
|
2 // Reads an AC-3 stream from stdin, decodes and downmixes to s16 stereo PCM
|
|
3 // and writes it to stdout. The resulting stream is playable with sox:
|
3396
|
4 // play -c 2 -r 48000 out.sw
|
|
5
|
3507
|
6 //#define TIMING //needs Pentium or newer
|
|
7
|
3396
|
8 #include <stdio.h>
|
|
9 #include <stdlib.h>
|
|
10 #include <inttypes.h>
|
12966
|
11 #include <string.h>
|
3396
|
12
|
|
13 #include "a52.h"
|
3908
|
14 #include "mm_accel.h"
|
3579
|
15 #include "../cpudetect.h"
|
3396
|
16
|
|
17 static sample_t * samples;
|
|
18 static a52_state_t state;
|
|
19 static uint8_t buf[3840];
|
|
20 static int buf_size=0;
|
|
21
|
|
22 static int16_t out_buf[6*256*6];
|
|
23
|
12966
|
24 void mp_msg_c( int x, const char *format, ... ) // stub for cpudetect.c
|
|
25 {
|
|
26 }
|
|
27
|
3507
|
28 #ifdef TIMING
|
|
29 static inline long long rdtsc()
|
|
30 {
|
|
31 long long l;
|
|
32 asm volatile( "rdtsc\n\t"
|
|
33 : "=A" (l)
|
|
34 );
|
|
35 // printf("%d\n", int(l/1000));
|
|
36 return l;
|
|
37 }
|
|
38
|
|
39 #define STARTTIMING t=rdtsc();
|
|
40 #define ENDTIMING sum+=rdtsc()-t; t=rdtsc();
|
|
41 #else
|
|
42 #define STARTTIMING ;
|
|
43 #define ENDTIMING ;
|
|
44 #endif
|
|
45
|
|
46
|
25100
|
47 int main(void){
|
3396
|
48 int accel=0;
|
|
49 int sample_rate=0;
|
|
50 int bit_rate=0;
|
3507
|
51 #ifdef TIMING
|
3511
|
52 long long t, sum=0, min=256*256*256*64;
|
3507
|
53 #endif
|
3396
|
54
|
3579
|
55 FILE *temp= stdout;
|
|
56 stdout= stderr; //EVIL HACK FIXME
|
|
57 GetCpuCaps(&gCpuCaps);
|
|
58 stdout= temp;
|
3908
|
59 // gCpuCaps.hasMMX=0;
|
|
60 // gCpuCaps.hasSSE=0;
|
|
61 if(gCpuCaps.hasMMX) accel |= MM_ACCEL_X86_MMX;
|
|
62 if(gCpuCaps.hasMMX2) accel |= MM_ACCEL_X86_MMXEXT;
|
|
63 if(gCpuCaps.hasSSE) accel |= MM_ACCEL_X86_SSE;
|
|
64 if(gCpuCaps.has3DNow) accel |= MM_ACCEL_X86_3DNOW;
|
|
65 // if(gCpuCaps.has3DNowExt) accel |= MM_ACCEL_X86_3DNOWEXT;
|
3579
|
66
|
3396
|
67 samples = a52_init (accel);
|
|
68 if (samples == NULL) {
|
|
69 fprintf (stderr, "A52 init failed\n");
|
|
70 return 1;
|
|
71 }
|
|
72
|
|
73 while(1){
|
|
74 int length,i;
|
|
75 int16_t *s16;
|
|
76 sample_t level=1, bias=384;
|
|
77 int flags=0;
|
3565
|
78 int channels=0;
|
3396
|
79
|
|
80 while(buf_size<7){
|
|
81 int c=getchar();
|
|
82 if(c<0) goto eof;
|
|
83 buf[buf_size++]=c;
|
|
84 }
|
3507
|
85 STARTTIMING
|
3396
|
86 length = a52_syncinfo (buf, &flags, &sample_rate, &bit_rate);
|
3507
|
87 ENDTIMING
|
3396
|
88 if(!length){
|
|
89 // bad file => resync
|
|
90 memcpy(buf,buf+1,6);
|
|
91 --buf_size;
|
|
92 continue;
|
|
93 }
|
|
94 fprintf(stderr,"sync. %d bytes 0x%X %d Hz %d kbit\n",length,flags,sample_rate,bit_rate);
|
|
95 while(buf_size<length){
|
|
96 buf[buf_size++]=getchar();
|
|
97 }
|
|
98
|
|
99 buf_size=0;
|
|
100
|
|
101 // decode:
|
3908
|
102 flags=A52_STEREO; //A52_STEREO; //A52_DOLBY; //A52_STEREO; // A52_DOLBY // A52_2F2R // A52_3F2R | A52_LFE
|
3565
|
103 channels=2;
|
|
104
|
3396
|
105 flags |= A52_ADJUST_LEVEL;
|
3507
|
106 STARTTIMING
|
3396
|
107 if (a52_frame (&state, buf, &flags, &level, bias))
|
|
108 { fprintf(stderr,"error at decoding\n"); continue; }
|
3507
|
109 ENDTIMING
|
3396
|
110
|
|
111 // a52_dynrng (&state, NULL, NULL); // disable dynamic range compensation
|
|
112
|
3579
|
113 STARTTIMING
|
3908
|
114 a52_resample_init(accel,flags,channels);
|
3396
|
115 s16 = out_buf;
|
|
116 for (i = 0; i < 6; i++) {
|
|
117 if (a52_block (&state, samples))
|
|
118 { fprintf(stderr,"error at sampling\n"); break; }
|
3565
|
119 // float->int + channels interleaving:
|
|
120 s16+=a52_resample(samples,s16);
|
3579
|
121 ENDTIMING
|
3396
|
122 }
|
3511
|
123 #ifdef TIMING
|
|
124 if(sum<min) min=sum;
|
|
125 sum=0;
|
|
126 #endif
|
3908
|
127 fwrite(out_buf,6*256*2*channels,1,stdout);
|
3396
|
128
|
|
129 }
|
|
130
|
|
131 eof:
|
3507
|
132 #ifdef TIMING
|
3511
|
133 fprintf(stderr, "%4.4fk cycles ",min/1000.0);
|
|
134 sum=0;
|
3507
|
135 #endif
|
3396
|
136 }
|