Add call to parent constructor.
[asdcplib-cth.git] / src / SyncEncoder.c
1 /*
2 Copyright (c) 2013-2013, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14    derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 /*! \file    SyncEncoder.c
28     \version $Id: SyncEncoder.c,v 1.1 2013/04/12 23:39:31 mikey Exp $
29     \brief   Implementation of Atmos Sync Frame Encoder
30 */
31
32 #include "SyncEncoder.h"
33 #include "CRC16.h"
34
35 #include <memory.h>
36
37 void ConstructFrame(LPSYNCENCODER       pSyncEncoder,
38                                         INT                             iFrameIndex);
39
40 FLOAT SEWriteBits(      INT                     iSampleRate,            /* In:  Sample rate of signal */
41                                         FLOAT           *pfAudioBuffer,         /* Out: Audio buffer containing signal */
42                                         INT                     iBits,                          /* In:  Number of bits to write */
43                                         BYTE            *pbyData,                       /* In:  Data to write */
44                                         FLOAT           fSymbolPhase);          /* In:  Symbol phase */
45
46
47
48 INT SyncEncoderInit(LPSYNCENCODER               pSyncEncoder,   /* Out: SYNCENCODER structure to be initialized */
49                                         INT                                     iSampleRate,    /* In:  Signal sample rate */
50                                         INT                                     iFrameRate,             /* In:  frame rate */
51                                         LPUUIDINFORMATION       pUUID)                  /* In:  UUID */
52 {
53         pSyncEncoder->iError = SYNC_ENCODER_ERROR_NONE;
54
55         /* Check and set sample rate */
56         pSyncEncoder->iSymbolLength = 1;
57         switch(iSampleRate){
58                 case 48000:
59                         pSyncEncoder->iSampleRate = iSampleRate;
60                         pSyncEncoder->iSymbolLength = SYMBOL_LENGTH_48;
61                 break;
62                 case 96000:
63                         pSyncEncoder->iSampleRate = iSampleRate;
64                         pSyncEncoder->iSymbolLength = SYMBOL_LENGTH_96;
65                 break;
66                 default:
67                         pSyncEncoder->iError = SYNC_ENCODER_ERROR_INVALID_SR;
68         };
69
70         if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
71                 return pSyncEncoder->iError;
72         }
73
74         /* check and set frame rate */
75         switch(iFrameRate){
76                 case 24:
77                         pSyncEncoder->iFrameRate = iFrameRate;
78                         pSyncEncoder->iFrameRateCode = 0;
79                         pSyncEncoder->iPacketsPerFrame = 4;
80                 break;
81                 case 25:
82                         pSyncEncoder->iFrameRate = iFrameRate;
83                         pSyncEncoder->iFrameRateCode = 1;
84                         pSyncEncoder->iPacketsPerFrame = 4;
85                 break;
86                 case 30:
87                         pSyncEncoder->iFrameRate = iFrameRate;
88                         pSyncEncoder->iFrameRateCode = 2;
89                         pSyncEncoder->iPacketsPerFrame = 4;
90                 break;
91                 case 48:
92                         pSyncEncoder->iFrameRate = iFrameRate;
93                         pSyncEncoder->iFrameRateCode = 3;
94                         pSyncEncoder->iPacketsPerFrame = 2;
95                 break;
96                 case 50:
97                         pSyncEncoder->iFrameRate = iFrameRate;
98                         pSyncEncoder->iFrameRateCode = 4;
99                         pSyncEncoder->iPacketsPerFrame = 2;
100                 break;
101                 case 60:
102                         pSyncEncoder->iFrameRate = iFrameRate;
103                         pSyncEncoder->iFrameRateCode = 5;
104                         pSyncEncoder->iPacketsPerFrame = 2;
105                 break;
106                 case 96:
107                         pSyncEncoder->iFrameRate = iFrameRate;
108                         pSyncEncoder->iFrameRateCode = 6;
109                         pSyncEncoder->iPacketsPerFrame = 1;
110                 break;
111                 case 100:
112                         pSyncEncoder->iFrameRate = iFrameRate;
113                         pSyncEncoder->iFrameRateCode = 7;
114                         pSyncEncoder->iPacketsPerFrame = 1;
115                 break;
116                 case 120:
117                         pSyncEncoder->iFrameRate = iFrameRate;
118                         pSyncEncoder->iFrameRateCode = 8;
119                         pSyncEncoder->iPacketsPerFrame = 1;
120                 break;
121                 default:
122                         pSyncEncoder->iError = SYNC_ENCODER_ERROR_INVALID_FR;
123         };
124
125         if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
126                 return pSyncEncoder->iError;
127         }
128
129         /* calculate required buffer length */
130         pSyncEncoder->iAudioBufferLength = pSyncEncoder->iSampleRate / pSyncEncoder->iFrameRate;
131
132         /* Calculate total packet bits including wash bits */
133         pSyncEncoder->iPacketBits = pSyncEncoder->iAudioBufferLength / (pSyncEncoder->iSymbolLength * pSyncEncoder->iPacketsPerFrame);
134
135         /* Initialize symbol phase */
136         pSyncEncoder->fSymbolPhase = 1.0f;
137
138         /* Initialize UUD information */
139         pSyncEncoder->iUUIDSubIndex = 0;
140         memcpy(&pSyncEncoder->UUID,pUUID,sizeof(UUIDINFORMATION));
141
142         return pSyncEncoder->iError;
143 }
144
145 INT GetSyncEncoderAudioBufferLength(LPSYNCENCODER pSyncEncoder) /* In: Sync encoder structure */
146 {
147         if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
148                 return pSyncEncoder->iError;
149         }
150
151         return pSyncEncoder->iAudioBufferLength;
152 }
153
154
155
156 INT EncodeSync( LPSYNCENCODER   pSyncEncoder,   /* In:  Sync encoder structure */
157                                 INT                             iBufferLength,  /* In:  Length of audio buffer */
158                                 FLOAT                   *pfAudioBuffer, /* Out: Audio buffer with signal */
159                                 INT                             iFrameIndex)    /* In:  Frame Index */
160 {
161         INT             n;
162         INT             iBufferIndex;
163
164
165         if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
166                 return pSyncEncoder->iError;
167         }
168         if(iBufferLength != pSyncEncoder->iAudioBufferLength){
169                 return SYNC_ENCODER_ERROR_INVALID_BL;
170         }
171
172         iBufferIndex = 0;
173         for(n = 0; n < pSyncEncoder->iPacketsPerFrame; n ++){
174                 /* Construct message */
175                 ConstructFrame(pSyncEncoder,iFrameIndex);
176
177                 /* Write Message */
178                 pSyncEncoder->fSymbolPhase = SEWriteBits(pSyncEncoder->iSampleRate,
179                                                                                                 &pfAudioBuffer[iBufferIndex],
180                                                                                                 pSyncEncoder->iPacketBits,
181                                                                                                 pSyncEncoder->abyPacket,
182                                                                                                 pSyncEncoder->fSymbolPhase);
183
184                 iBufferIndex += (pSyncEncoder->iPacketBits * pSyncEncoder->iSymbolLength);
185
186         }
187
188         return pSyncEncoder->iError;
189 }
190
191 void ConstructFrame(LPSYNCENCODER       pSyncEncoder,
192                                         INT                             iFrameIndex)
193 {
194         USHORT  ushCRC;
195         BYTE    byByte;
196         INT             iUUIDIndex;
197
198         /* Flush the packet buffer */
199         memset(pSyncEncoder->abyPacket,0,MAX_PACKET);
200
201         /* Sync Header */
202         pSyncEncoder->abyPacket[0] = SYNC_HEADER1;
203         pSyncEncoder->abyPacket[1] = SYNC_HEADER2;
204
205         /* Frame Rate code */
206         byByte = 0;
207         byByte = (unsigned char)(pSyncEncoder->iFrameRateCode << 4);
208
209         /* UUID sub index */
210         byByte |= (unsigned char)(pSyncEncoder->iUUIDSubIndex & 0x3);
211
212         pSyncEncoder->abyPacket[2] = byByte;
213
214         /* UUID Sub */
215         iUUIDIndex = pSyncEncoder->iUUIDSubIndex << 2;
216         pSyncEncoder->abyPacket[3] = pSyncEncoder->UUID.abyUUIDBytes[iUUIDIndex];
217         pSyncEncoder->abyPacket[4] = pSyncEncoder->UUID.abyUUIDBytes[iUUIDIndex + 1];
218         pSyncEncoder->abyPacket[5] = pSyncEncoder->UUID.abyUUIDBytes[iUUIDIndex + 2];
219         pSyncEncoder->abyPacket[6] = pSyncEncoder->UUID.abyUUIDBytes[iUUIDIndex + 3];
220
221         /* Update UUID sub index */
222         pSyncEncoder->iUUIDSubIndex ++;
223         pSyncEncoder->iUUIDSubIndex &= 0x3;
224
225         /* Frame Index */
226         byByte = (unsigned char)((iFrameIndex >> 16) & 0XFF);
227         pSyncEncoder->abyPacket[7] = byByte;
228         byByte = (unsigned char)((iFrameIndex >> 8) & 0XFF);
229         pSyncEncoder->abyPacket[8] = byByte;
230         byByte = (unsigned char)(iFrameIndex & 0XFF);
231         pSyncEncoder->abyPacket[9] = byByte;
232
233         /* calculate CRC */
234         ushCRC = CRC16(&pSyncEncoder->abyPacket[2],MESSAGE_TOTAL_BYTES - 4);
235
236         /* Insert CRC */
237         byByte = (unsigned char)((ushCRC >> 8) & 0XFF);
238         pSyncEncoder->abyPacket[10] = byByte;
239         byByte = (unsigned char)(ushCRC & 0XFF);
240         pSyncEncoder->abyPacket[11] = byByte;
241
242 }
243
244 static FLOAT g_afSymbol0_48[SYMBOL_LENGTH_48] = {
245         0.3827f,
246     0.9239f,
247     0.9239f,
248     0.3827f,
249 };
250
251 static FLOAT g_afSymbol1_48[SYMBOL_LENGTH_48] = {
252         0.7071f,
253     0.7071f,
254    -0.7071f,
255    -0.7071f,
256 };
257
258 static FLOAT g_afSymbol0_96[SYMBOL_LENGTH_96] = {
259         0.1951f,
260     0.5556f,
261     0.8315f,
262     0.9808f,
263     0.9808f,
264     0.8315f,
265     0.5556f,
266     0.1951f,
267 };
268
269 static FLOAT g_afSymbol1_96[SYMBOL_LENGTH_96] = {
270         0.3827f,
271     0.9239f,
272     0.9239f,
273     0.3827f,
274    -0.3827f,
275    -0.9239f,
276    -0.9239f,
277    -0.3827f,
278 };
279
280 /* Symbol gain */
281 static FLOAT g_fGain = 0.1f;
282
283 FLOAT SEWriteBits(      INT                     iSampleRate,            /* In:  Sample rate of signal */
284                                         FLOAT           *pfAudioBuffer,         /* Out: Audio buffer containing signal */
285                                         INT                     iBits,                          /* In:  Number of bits to write */
286                                         BYTE            *pbyData,                       /* In:  Data to write */
287                                         FLOAT           fSymbolPhase)           /* In:  Symbol phase */
288 {
289         INT             n;
290         INT             i;
291         INT             iSymbolLength;
292         FLOAT   *pfSymbol0;
293         FLOAT   *pfSymbol1;
294         BYTE    byByte;
295
296         /* Select the correct symbol length and symbol signal based on sample rate */
297         switch (iSampleRate){
298                 case 96000:
299                         iSymbolLength = SYMBOL_LENGTH_96;
300                         pfSymbol0 = g_afSymbol0_96;
301                         pfSymbol1 = g_afSymbol1_96;
302                 break;
303                 case 48000:
304                         iSymbolLength = SYMBOL_LENGTH_48;
305                         pfSymbol0 = g_afSymbol0_48;
306                         pfSymbol1 = g_afSymbol1_48;
307                 break;
308                 default:
309                         iSymbolLength = 0;
310                         pfSymbol0 = g_afSymbol0_96;
311                         pfSymbol1 = g_afSymbol1_96;
312         };
313
314         /* Write bits */
315         n = 0;
316         i = 0;
317         while(n < iBits){
318                 INT             k;
319                 FLOAT   *pfSymbol;
320
321                 /* Grab next byte of data */
322                 if(i == 0){
323                         byByte = *pbyData;
324                         pbyData ++;
325                 }
326
327                 pfSymbol = (byByte & 0x80) ? pfSymbol1 : pfSymbol0;
328
329                 for(k = 0; k < iSymbolLength; k ++){
330                         *pfAudioBuffer =  *pfSymbol * fSymbolPhase * g_fGain;
331                         pfAudioBuffer ++;
332                         pfSymbol ++;
333                 }
334
335                 fSymbolPhase *= (byByte & 0x80) ? 1.0f : -1.0f;
336
337                 byByte <<= 1;
338
339                 n ++;
340
341                 i ++;
342                 i &= 0x7;
343         }
344
345         return fSymbolPhase;
346 }