2 Copyright (c) 2013-2013, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
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.
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.
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
32 #include "SyncEncoder.h"
37 void ConstructFrame(LPSYNCENCODER pSyncEncoder,
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 */
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 */
53 pSyncEncoder->iError = SYNC_ENCODER_ERROR_NONE;
55 /* Check and set sample rate */
56 pSyncEncoder->iSymbolLength = 1;
59 pSyncEncoder->iSampleRate = iSampleRate;
60 pSyncEncoder->iSymbolLength = SYMBOL_LENGTH_48;
63 pSyncEncoder->iSampleRate = iSampleRate;
64 pSyncEncoder->iSymbolLength = SYMBOL_LENGTH_96;
67 pSyncEncoder->iError = SYNC_ENCODER_ERROR_INVALID_SR;
70 if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
71 return pSyncEncoder->iError;
74 /* check and set frame rate */
77 pSyncEncoder->iFrameRate = iFrameRate;
78 pSyncEncoder->iFrameRateCode = 0;
79 pSyncEncoder->iPacketsPerFrame = 4;
82 pSyncEncoder->iFrameRate = iFrameRate;
83 pSyncEncoder->iFrameRateCode = 1;
84 pSyncEncoder->iPacketsPerFrame = 4;
87 pSyncEncoder->iFrameRate = iFrameRate;
88 pSyncEncoder->iFrameRateCode = 2;
89 pSyncEncoder->iPacketsPerFrame = 4;
92 pSyncEncoder->iFrameRate = iFrameRate;
93 pSyncEncoder->iFrameRateCode = 3;
94 pSyncEncoder->iPacketsPerFrame = 2;
97 pSyncEncoder->iFrameRate = iFrameRate;
98 pSyncEncoder->iFrameRateCode = 4;
99 pSyncEncoder->iPacketsPerFrame = 2;
102 pSyncEncoder->iFrameRate = iFrameRate;
103 pSyncEncoder->iFrameRateCode = 5;
104 pSyncEncoder->iPacketsPerFrame = 2;
107 pSyncEncoder->iFrameRate = iFrameRate;
108 pSyncEncoder->iFrameRateCode = 6;
109 pSyncEncoder->iPacketsPerFrame = 1;
112 pSyncEncoder->iFrameRate = iFrameRate;
113 pSyncEncoder->iFrameRateCode = 7;
114 pSyncEncoder->iPacketsPerFrame = 1;
117 pSyncEncoder->iFrameRate = iFrameRate;
118 pSyncEncoder->iFrameRateCode = 8;
119 pSyncEncoder->iPacketsPerFrame = 1;
122 pSyncEncoder->iError = SYNC_ENCODER_ERROR_INVALID_FR;
125 if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
126 return pSyncEncoder->iError;
129 /* calculate required buffer length */
130 pSyncEncoder->iAudioBufferLength = pSyncEncoder->iSampleRate / pSyncEncoder->iFrameRate;
132 /* Calculate total packet bits including wash bits */
133 pSyncEncoder->iPacketBits = pSyncEncoder->iAudioBufferLength / (pSyncEncoder->iSymbolLength * pSyncEncoder->iPacketsPerFrame);
135 /* Initialize symbol phase */
136 pSyncEncoder->fSymbolPhase = 1.0f;
138 /* Initialize UUD information */
139 pSyncEncoder->iUUIDSubIndex = 0;
140 memcpy(&pSyncEncoder->UUID,pUUID,sizeof(UUIDINFORMATION));
142 return pSyncEncoder->iError;
145 INT GetSyncEncoderAudioBufferLength(LPSYNCENCODER pSyncEncoder) /* In: Sync encoder structure */
147 if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
148 return pSyncEncoder->iError;
151 return pSyncEncoder->iAudioBufferLength;
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 */
165 if(pSyncEncoder->iError != SYNC_ENCODER_ERROR_NONE){
166 return pSyncEncoder->iError;
168 if(iBufferLength != pSyncEncoder->iAudioBufferLength){
169 return SYNC_ENCODER_ERROR_INVALID_BL;
173 for(n = 0; n < pSyncEncoder->iPacketsPerFrame; n ++){
174 /* Construct message */
175 ConstructFrame(pSyncEncoder,iFrameIndex);
178 pSyncEncoder->fSymbolPhase = SEWriteBits(pSyncEncoder->iSampleRate,
179 &pfAudioBuffer[iBufferIndex],
180 pSyncEncoder->iPacketBits,
181 pSyncEncoder->abyPacket,
182 pSyncEncoder->fSymbolPhase);
184 iBufferIndex += (pSyncEncoder->iPacketBits * pSyncEncoder->iSymbolLength);
188 return pSyncEncoder->iError;
191 void ConstructFrame(LPSYNCENCODER pSyncEncoder,
198 /* Flush the packet buffer */
199 memset(pSyncEncoder->abyPacket,0,MAX_PACKET);
202 pSyncEncoder->abyPacket[0] = SYNC_HEADER1;
203 pSyncEncoder->abyPacket[1] = SYNC_HEADER2;
205 /* Frame Rate code */
207 byByte = (unsigned char)(pSyncEncoder->iFrameRateCode << 4);
210 byByte |= (unsigned char)(pSyncEncoder->iUUIDSubIndex & 0x3);
212 pSyncEncoder->abyPacket[2] = byByte;
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];
221 /* Update UUID sub index */
222 pSyncEncoder->iUUIDSubIndex ++;
223 pSyncEncoder->iUUIDSubIndex &= 0x3;
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;
234 ushCRC = CRC16(&pSyncEncoder->abyPacket[2],MESSAGE_TOTAL_BYTES - 4);
237 byByte = (unsigned char)((ushCRC >> 8) & 0XFF);
238 pSyncEncoder->abyPacket[10] = byByte;
239 byByte = (unsigned char)(ushCRC & 0XFF);
240 pSyncEncoder->abyPacket[11] = byByte;
244 static FLOAT g_afSymbol0_48[SYMBOL_LENGTH_48] = {
251 static FLOAT g_afSymbol1_48[SYMBOL_LENGTH_48] = {
258 static FLOAT g_afSymbol0_96[SYMBOL_LENGTH_96] = {
269 static FLOAT g_afSymbol1_96[SYMBOL_LENGTH_96] = {
281 static FLOAT g_fGain = 0.1f;
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 */
296 /* Select the correct symbol length and symbol signal based on sample rate */
297 switch (iSampleRate){
299 iSymbolLength = SYMBOL_LENGTH_96;
300 pfSymbol0 = g_afSymbol0_96;
301 pfSymbol1 = g_afSymbol1_96;
304 iSymbolLength = SYMBOL_LENGTH_48;
305 pfSymbol0 = g_afSymbol0_48;
306 pfSymbol1 = g_afSymbol1_48;
310 pfSymbol0 = g_afSymbol0_96;
311 pfSymbol1 = g_afSymbol1_96;
321 /* Grab next byte of data */
327 pfSymbol = (byByte & 0x80) ? pfSymbol1 : pfSymbol0;
329 for(k = 0; k < iSymbolLength; k ++){
330 *pfAudioBuffer = *pfSymbol * fSymbolPhase * g_fGain;
335 fSymbolPhase *= (byByte & 0x80) ? 1.0f : -1.0f;