`Page 1/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`1
`++++++¬
`…
`¬2
`Copyright (c) 2001 BeComm Corporation¬
`3
`¬4
`Filename:¬
`5
`¬6
` audiosync.c¬
`7
`¬8
`Group Name:¬
`9
`¬10
`¬11
`¬12
`Overview:¬
`13
`¬14
` This bead adjusts the audio stream by either¬
`15
` dropping data, padding data or resampling data¬
`16
` in an effort to make the path render clock match¬
`17
` the path sample clock.¬
`18
`¬19
` This is done by computing the error in ms,¬
`20
` smoothing the error over successive calls to¬
`21
` the handler to reduce the noise in the signal.¬
`22
` A damping factor is applied to correction to¬
`23
` reduce the likelihood of over correction. Note there¬
`24
` is a significant amount of buffering between this¬
`25
` bead and playout which adds latency to the feedback.¬
`26
` Without damping it would be very possible to over¬
`27
` correct and end up cycling.¬
`28
`¬29
` When a correction value has been found the¬
`30
` stream is modified if necessary to¬
`31
` bring the error back into tolerance.¬
`32
`¬33
` If the audio is very early, the packet is duplicated¬
`34
` as necessary to delay it.¬
`35
`¬36
` If the audio is very late, part or all of the packet¬
`37
` is discarded.¬
`38
`¬39
` If the audio is a little early or late, the packet¬
`40
` is resampled to stretch or shrink it.¬
`41
` ¬
`42
`Notes:¬
`43
`¬44
`
`Page 1 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 2/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
` Currently only supports 16-bit audio streams.¬
`45
` Supporting 8-bits would be relatively trivial.¬
`46
`¬47
`Owner:¬
`48
`¬49
` Guy Carpenter (guyc) 28-Sep-2001¬
`50
`¬51
`-------------------------------------------------------------------------
`52
`----*/¬
`…
`¬53
`#define SOS_DEBUG_ZONE "/beads/audiosync"¬
`54
`¬55
`#include <sosstrings.h>¬
`56
`#include <sosmultimedia.h>¬
`57
`¬58
`SOS_SOURCE_VERSION (¬
`59
` "$Id: audiosync.c,v 1.16 2001/11/10 00:53:11 guyc Exp $"¬
`60
`);¬
`61
`¬62
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`63
`++++++¬
`…
`Named Constants¬
`64
`-------------------------------------------------------------------------
`65
`----*/¬
`…
`¬66
`/*¬
`67
` * Name of bead¬
`68
` */¬
`69
`static const char BEAD_NAME[] = "audiosync";¬
`70
`¬71
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`72
`++++++¬
`…
`Structs¬
`73
`-------------------------------------------------------------------------
`74
`----*/¬
`…
`¬75
`typedef struct _SLIDING_AVG {¬
`76
` SOS_UINT32 Size; /* total size we can contain */¬
`77
` SOS_UINT32 Count; /* current number of entries */¬
`78
` SOS_UINT32 Index; /* index of next new value */¬
`79
` SOS_INT32 Sum; /* total of count values */¬
`80
` SOS_INT32 * Value; /* count values */¬
`81
`} SLIDING_AVG;¬
`82
`¬83
`static const¬
`84
`
`Page 2 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 3/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`85
`86
`87
`88
`89
`90
`91
`92
`93
`94
`95
`96
`97
`98
`99
`100
`101
`102
`103
`104
`105
`106
`107
`108
`109
`110
`111
`112
`113
`114
`115
`116
`117
`118
`119
`120
`121
`122
`123
`124
`125
`126
`…
`127
`128
`
`struct {¬
` const char * Name;¬
` SOS_UINT32 Default;¬
`} g_ParameterList[] = {¬
` {"AudioSync/EarlyReject", 5000},¬
` {"AudioSync/LateReject", 500000},¬
` {"AudioSync/EarlyCopy", 50},¬
` {"AudioSync/LateDrop", 50},¬
` {"AudioSync/EarlyResample", 4},¬
` {"AudioSync/LateResample", 4},¬
` {"AudioSync/MinResamplePercent", 99},¬
` {"AudioSync/MaxResamplePercent", 101},¬
` {"AudioSync/Smoothing", 8},¬
` {"AudioSync/Damping", 8},¬
` {NULL,0}¬
`};¬
` ¬
`typedef enum {¬
` PARAM_EARLY_REJECT = 0,¬
` PARAM_LATE_REJECT = 1,¬
` PARAM_EARLY_COPY = 2,¬
` PARAM_LATE_DROP = 3,¬
` PARAM_EARLY_RESAMPLE = 4,¬
` PARAM_LATE_RESAMPLE = 5,¬
` PARAM_MIN_RESAMPLE_PERCENT = 6,¬
` PARAM_MAX_RESAMPLE_PERCENT = 7,¬
` PARAM_SMOOTHING = 8,¬
` PARAM_DAMPING = 9,¬
` PARAM_COUNT = 10¬
`} PARAM_INDEX;¬
`¬
`typedef struct _AUDIOSYNC_CONTEXT {¬
` SOS_BOOLEAN ContextReady;¬
` SOS_ISAMPLECLOCK * MasterClock;¬
` SOS_ISAMPLECLOCK * RenderClock;¬
` SOS_IAUDIOCONTEXT * AudioContext;¬
` SLIDING_AVG AvgError;¬
` SOS_BOOLEAN First;¬
` SOS_INT32 Param[PARAM_COUNT];¬
`} AUDIOSYNC_CONTEXT;¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Utility Functions¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`
`Page 3 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 4/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`128…
`129
`130
`131
`132
`133
`134
`135
`136
`137
`138
`139
`140
`…
`141
`142
`143
`144
`…
`145
`146
`…
`147
`148
`149
`150
`151
`152
`153
`154
`155
`156
`157
`158
`159
`160
`161
`162
`163
`164
`165
`166
`167
`168
`169
`
`++++*/¬
`¬
`static¬
`SOS_UINT32¬
`Scale(¬
` SOS_UINT32 Value,¬
` SOS_UINT32 Numerator,¬
` SOS_UINT32 Denominator¬
`)¬
`{¬
` SOS_UINT32 whole = Value / Denominator;¬
` SOS_UINT32 remain = Value % Denominator;¬
` SOS_UINT32 result = whole * Numerator + remain * Numerator /
`Denominator;¬
` return result;¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Params¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++*/¬
`static¬
`SOS_UINT32¬
`IntParamGet(¬
` SOS_PATH * Path,¬
` const char * Name,¬
` SOS_UINT32 Default¬
`)¬
`{¬
` SOS_UINT32 value;¬
` SOS_REGOBJECT *object = NULL;¬
` if (SOS_FAILED(¬
` SOS_Path_AttributeGet(¬
` Path,¬
` Name,¬
` &object)) ||¬
` SOS_FAILED(¬
` SOS_RegObject_Int32ValueGet(¬
` object,¬
` &value¬
` ))) {¬
` value = Default;¬
` }¬
` SOS_RegObject_Release(object);¬
`
`Page 4 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 5/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`170
`171
`172
`173
`174
`175
`176
`177
`178
`179
`180
`181
`182
`183
`184
`185
`186
`187
`188
`189
`190
`…
`191
`192
`…
`193
`194
`195
`196
`197
`198
`199
`200
`201
`202
`203
`204
`205
`206
`207
`208
`209
`210
`211
`212
`
` return value;¬
`}¬
`¬
`static¬
`void¬
`ParamsGet(¬
` SOS_PATH * Path,¬
` AUDIOSYNC_CONTEXT * Context¬
`)¬
`{¬
` size_t i;¬
` for (i=0;g_ParameterList[i].Name;i++) {¬
` Context->Param[i] = IntParamGet(¬
` Path,¬
` g_ParameterList[i].Name,¬
` g_ParameterList[i].Default¬
` );¬
` }¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Sliding Average Routines¬
`-------------------------------------------------------------------------
`----*/¬
`static¬
`SOS_STATUS¬
`SlidingAvg_Init(¬
` SLIDING_AVG * Avg,¬
` SOS_UINT32 Size¬
`)¬
`{¬
`// SOS_Debug_StringPrint("SlidingAvg_Init\n");¬
` Avg->Value = SOS_Mem_Alloc(sizeof(SOS_UINT32)*Size);¬
` SOS_memset(Avg->Value, 0, sizeof(SLIDING_AVG));¬
` Avg->Size = Size;¬
` return Avg->Value ? SOS_Success : SOS_ErrorResourceAllocation;¬
`}¬
`¬
`static¬
`void¬
`SlidingAvg_Uninit(¬
` SLIDING_AVG * Avg¬
`)¬
`{¬
`
`Page 5 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 6/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`213
`214
`215
`216
`217
`218
`219
`220
`221
`222
`223
`224
`225
`226
`227
`228
`229
`230
`231
`232
`233
`234
`235
`236
`237
`238
`239
`240
`241
`242
`243
`244
`245
`246
`247
`248
`249
`250
`251
`252
`…
`253
`254
`…
`255
`
` SOS_Mem_Free(Avg->Value);¬
`}¬
` ¬
`¬
`static¬
`SOS_INT32¬
`SlidingAvg_Add(¬
` SLIDING_AVG * Avg,¬
` SOS_INT32 Value¬
`)¬
`{¬
` SOS_DEBUGOUT_DETAIL(¬
` "SlidingAvg_Add gets %ld\n",¬
` Value¬
` );¬
` ¬
` if (Avg->Count==Avg->Size) {¬
` Avg->Sum-=Avg->Value[Avg->Index];¬
` } else {¬
` Avg->Count++;¬
` }¬
` Avg->Value[Avg->Index]=Value;¬
` Avg->Sum+=Value;¬
`¬
` Avg->Index++;¬
` if (Avg->Index==Avg->Size) {¬
` Avg->Index=0;¬
` }¬
`¬
` SOS_DEBUGOUT_DETAIL(¬
` "SlidingAvg_Add returns %ld/%lu=%ld\n",¬
` Avg->Sum,¬
` Avg->Count,¬
` Avg->Sum/(SOS_INT32)Avg->Count¬
` );¬
` return Avg->Sum/(SOS_INT32)Avg->Count;¬
`}¬
`¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Context Stuff¬
`-------------------------------------------------------------------------
`----*/¬
`¬
`
`Page 6 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 7/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`256
`257
`258
`259
`260
`261
`262
`263
`264
`265
`266
`267
`268
`269
`270
`271
`272
`273
`274
`275
`276
`277
`278
`279
`280
`281
`282
`283
`284
`285
`286
`287
`288
`289
`290
`291
`292
`293
`…
`294
`295
`…
`296
`297
`298
`
`static¬
`void¬
`AudioSync_ContextDestroy(¬
` AUDIOSYNC_CONTEXT * Context¬
`)¬
`{¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_ContextDestroy\n");¬
`¬
` if (Context) {¬
` SlidingAvg_Uninit(&(Context->AvgError));¬
` SOS_Interface_Release(Context->MasterClock);¬
` SOS_Interface_Release(Context->RenderClock);¬
` SOS_Interface_Release(Context->AudioContext);¬
` SOS_Mem_Free(Context);¬
` }¬
`}¬
`¬
`static¬
`AUDIOSYNC_CONTEXT *¬
`AudioSync_ContextCreate(¬
` void¬
`)¬
`{¬
` AUDIOSYNC_CONTEXT *context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_ContextCreate\n");¬
`¬
` context = SOS_Mem_Alloc(sizeof(*context));¬
` if (context) {¬
` SOS_memset(context, 0, sizeof(*context));¬
`// SlidingAvg_Init(&(context->AvgError),SMOOTH_FACTOR);¬
`context->First = SOS_True;¬
` }¬
`¬
` return context;¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++*/¬
`¬
`static¬
`SOS_STATUS¬
`
`Page 7 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 8/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`299
`300
`301
`302
`303
`304
`305
`306
`307
`308
`309
`310
`311
`312
`313
`314
`315
`316
`317
`318
`319
`320
`321
`322
`323
`324
`325
`326
`327
`328
`329
`330
`331
`332
`333
`334
`335
`336
`337
`338
`339
`340
`341
`342
`343
`
`AudioSync_KeyCreate(¬
` SOS_PATH *Path,¬
` SOS_MESSAGE *Message¬
`)¬
`{¬
` static SOS_UINT32 s_UniqueId = 0;¬
` SOS_REGOBJECT* uniqueSessionKey;¬
` ¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_KeyCreate\n");¬
`¬
` uniqueSessionKey = SOS_UInt32_Create(s_UniqueId++);¬
` SOS_Path_SessionKeySet(Path, uniqueSessionKey);¬
` SOS_RegObject_Release(uniqueSessionKey);¬
`¬
` return SOS_Success;¬
`}¬
`¬
`SOS_STATUS¬
`ContextClockGet(¬
` SOS_PATH * Path,¬
` const char * Name,¬
` SOS_ISAMPLECLOCK ** ISampleClock¬
`)¬
`{¬
` SOS_STATUS status;¬
` SOS_REGOBJECT *object;¬
` SOS_ISAMPLECLOCK *iSampleClock = NULL;¬
` ¬
` SOS_DEBUGOUT_FUNC_TRACE("ContextClockGet\n");¬
`¬
` status = SOS_Path_AttributeGet(¬
` Path,¬
` Name,¬
` &object¬
` );¬
`¬
` SOS_ASSERT_SOFT_ERROR(¬
` SOS_SUCCEEDED(status),¬
` "Clock not found"¬
` );¬
` ¬
` if (SOS_SUCCEEDED(status)) {¬
` status = SOS_RegObject_InterfaceGet(¬
` object,¬
` SOS_ISAMPLECLOCK_ID,¬
`
`Page 8 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/audiosync.c
`Page 9/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`344
`345
`346
`347
`348
`349
`350
`351
`352
`353
`354
`355
`356
`357
`358
`359
`360
`361
`362
`363
`364
`365
`366
`367
`368
`369
`370
`371
`372
`373
`374
`375
`376
`377
`378
`379
`380
`381
`382
`383
`384
`385
`386
`387
`388
`
` (void**)&iSampleClock¬
` );¬
` SOS_RegObject_Release(object);¬
` }¬
`¬
` if (ISampleClock) {¬
` *ISampleClock = iSampleClock;¬
` } else {¬
` SOS_Interface_Release(iSampleClock);¬
` status = SOS_ErrorParameter;¬
` }¬
`¬
` return status;¬
`}¬
`¬
`¬
`SOS_STATUS¬
`AudioContextGet(¬
` SOS_PATH * Path,¬
` const char * Name,¬
` SOS_IAUDIOCONTEXT ** IAudioContext¬
`)¬
`{¬
` SOS_STATUS status;¬
` SOS_REGOBJECT *contextObject;¬
` SOS_IAUDIOCONTEXT *iAudioContext = NULL;¬
` ¬
` status = SOS_Path_AttributeGet(¬
` Path,¬
` Name,¬
` &contextObject¬
` );¬
`¬
` SOS_ASSERT_SOFT_ERROR(¬
` SOS_SUCCEEDED(status),¬
` "Path context does not contain an audio context"¬
` );¬
` ¬
` if (SOS_SUCCEEDED(status)) {¬
` status = SOS_RegObject_InterfaceGet(¬
` contextObject,¬
` SOS_IAUDIOCONTEXT_ID,¬
` (void**)&iAudioContext¬
` );¬
` ¬
`
`Page 9 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 10/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`389
`390
`391
`392
`393
`394
`395
`396
`397
`398
`399
`400
`401
`402
`403
`404
`405
`406
`407
`408
`409
`410
`411
`412
`413
`414
`415
`416
`417
`418
`419
`420
`421
`422
`423
`424
`425
`426
`427
`428
`429
`430
`431
`432
`433
`
` SOS_ASSERT_SOFT_ERROR(¬
` SOS_SUCCEEDED(status),¬
` "Audio context does not support required interface"¬
` );¬
` ¬
` SOS_RegObject_Release(contextObject);¬
` }¬
`¬
` *IAudioContext = iAudioContext;¬
`¬
` return status;¬
`}¬
`¬
`¬
`¬
`static¬
`SOS_STATUS¬
`AudioSync_ContextPrepare(¬
` AUDIOSYNC_CONTEXT *Context,¬
` SOS_PATH *Path¬
`)¬
`{¬
` SOS_STATUS status;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_ContextPrepare\n");¬
`¬
` if (!Context->RenderClock) {¬
` ContextClockGet(¬
` Path,¬
` SOS_RENDERCLOCK_NAME,¬
` &Context->RenderClock¬
` );¬
` }¬
`¬
` if (!Context->MasterClock) {¬
` ContextClockGet(¬
` Path,¬
` SOS_MASTERCLOCK_NAME,¬
` &Context->MasterClock¬
` );¬
` }¬
`¬
` if (!Context->AudioContext) {¬
` AudioContextGet(¬
` Path,¬
`
`Page 10 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 11/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`434
`435
`436
`437
`438
`439
`440
`441
`442
`443
`444
`445
`446
`447
`448
`449
`450
`451
`452
`453
`454
`455
`456
`457
`458
`459
`460
`461
`462
`463
`464
`…
`465
`466
`…
`467
`468
`469
`470
`471
`472
`473
`474
`475
`476
`
` SOS_AUDIOCONTEXT_NAME,¬
` &Context->AudioContext¬
` );¬
` }¬
`¬
` if (Context->AudioContext &&¬
` Context->MasterClock &&¬
` Context->RenderClock) {¬
` ParamsGet(Path, Context);¬
` SlidingAvg_Init(¬
` &(Context->AvgError),¬
` Context->Param[PARAM_SMOOTHING]);¬
` status = SOS_Success;¬
` } else {¬
` status = SOS_Error;¬
` }¬
`¬
` /*¬
` * Success only if we got all of the components¬
` */¬
` SOS_DEBUGOUT_DETAIL(¬
` "AudioContext %s MasterClock %s RenderClock %s\n",¬
` Context->AudioContext ? "yes" : "no",¬
` Context->MasterClock ? "yes" : "no",¬
` Context->RenderClock ? "yes" : "no"¬
` );¬
` ¬
` return status;¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Adjustment¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++*/¬
`static¬
`SOS_INT32 *¬
`AudioSync_Resample16(¬
` SOS_INT32 * InBuffer,¬
` SOS_UINT32 InCount,¬
` SOS_UINT32 OutCount¬
`)¬
`{¬
` SOS_INT32 * outBuffer = SOS_Mem_Alloc(OutCount * sizeof(SOS_INT32));¬
` SOS_UINT32 i;¬
`
`Page 11 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 12/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`477
`478
`479
`480
`481
`482
`483
`484
`485
`486
`487
`488
`489
`490
`491
`492
`493
`494
`495
`496
`497
`498
`499
`500
`501
`502
`503
`504
`505
`506
`507
`508
`509
`510
`511
`512
`513
`514
`515
`516
`517
`518
`519
`520
`521
`
`¬
` if (outBuffer) {¬
` for (i=0;i<OutCount;i++) {¬
` outBuffer[i]=InBuffer[i*InCount/OutCount];¬
` }¬
` }¬
` return outBuffer;¬
`}¬
`¬
`static¬
`SOS_STATUS¬
`AudioSync_MessageFill(¬
` SOS_MESSAGE* Message,¬
` char Value¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` size_t length;¬
` void *buffer;¬
` ¬
` length = SOS_Message_LengthGet(Message);¬
` buffer = SOS_Mem_Alloc(length);¬
` ¬
` if (buffer) {¬
` // REVISIT - doesn't handle 8-bit silence¬
` SOS_memset(buffer, Value, length);¬
` SOS_Message_HeadDataPop(¬
` Message,¬
` length,¬
` NULL,¬
` NULL¬
` );¬
` SOS_Message_HeadDataPush(¬
` Message,¬
` buffer,¬
` length,¬
` SOS_Mem_Free¬
` );¬
` ¬
` } else {¬
` status = SOS_Error;¬
` }¬
`¬
` return status;¬
`}¬
`
`Page 12 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 13/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`522
`523
`524
`525
`526
`527
`528
`529
`530
`531
`532
`533
`534
`535
`536
`537
`538
`539
`540
`541
`542
`543
`544
`545
`546
`547
`548
`549
`550
`551
`552
`553
`554
`555
`556
`557
`558
`559
`560
`561
`562
`563
`564
`565
`566
`
` ¬
` ¬
`¬
`¬
`static¬
`SOS_STATUS¬
`AudioSync_Adjust(¬
` AUDIOSYNC_CONTEXT* Context,¬
` SOS_PATH* Path,¬
` SOS_MESSAGE* Message,¬
` SOS_CLOCK_TICK MasterEpoch,¬
` SOS_CLOCK_TICK RenderEpoch¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` SOS_INT32 early = (SOS_INT32)(MasterEpoch-RenderEpoch);¬
` SOS_INT32 avgEarly = SlidingAvg_Add(&(Context->AvgError),early);¬
` SOS_INT32 avgLate = -avgEarly;¬
` SOS_INT32 avgDelta = avgEarly>0 ? avgEarly : -avgEarly;¬
`¬
` SOS_DEBUGOUT_DETAIL(¬
` "AudioSync MasterEpoch=%lu RenderEpoch=%lu\n",¬
` MasterEpoch,¬
` RenderEpoch¬
` );¬
`¬
` /*¬
` * If master epoch > render epoch then we are early and should delay.¬
` */¬
`¬
` SOS_DEBUGOUT_DETAIL(¬
` "AudioSync reports %ld ms %s (avg %ld %s)\n",¬
` early>0 ? early : -early,¬
` early>0 ? "early" : "late",¬
` avgDelta,¬
` avgEarly>0 ? "early" : "late"¬
` );¬
`¬
`¬
` if (avgLate>Context->Param[PARAM_LATE_REJECT]) {¬
` SOS_DEBUGOUT_DETAIL("Audiosync dropping very late packet\n");¬
` status = SOS_Error;¬
` } else if (avgEarly>Context->Param[PARAM_EARLY_REJECT]) {¬
` SOS_DEBUGOUT_DETAIL("Audiosync silencing very early packet\n");¬
` Context->AudioContext->Unpack(¬
`
`Page 13 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 14/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`567
`568
`569
`570
`571
`572
`573
`574
`575
`576
`577
`578
`579
`580
`581
`582
`583
`584
`585
`586
`587
`588
`589
`590
`591
`592
`593
`594
`595
`596
`597
`598
`599
`600
`601
`602
`603
`604
`605
`606
`607
`608
`609
`610
`611
`
` Context->AudioContext,¬
` Message¬
` );¬
`¬
` /*¬
` * if it fails to fill the message it¬
` * leaves the message intact, and we return¬
` * the status which causes the message to¬
` * be discarded ultimately (which is fine)¬
` */¬
` status = AudioSync_MessageFill(Message, 0);¬
` ¬
` Context->AudioContext->Pack(¬
` Context->AudioContext,¬
` Message¬
` );¬
` ¬
` } else if (avgEarly>Context->Param[PARAM_EARLY_RESAMPLE] ||¬
` avgLate> Context->Param[PARAM_LATE_RESAMPLE]) {¬
` SOS_AUDIO_FORMAT format;¬
` SOS_UINT32 samples;¬
` SOS_UINT32 bytes;¬
` SOS_UINT32 quantum;¬
`¬
` /*¬
` * We are out of tolerance - need to adjust¬
` */¬
`¬
` Context->AudioContext->Unpack(¬
` Context->AudioContext,¬
` Message¬
` );¬
`¬
` Context->AudioContext->FormatGet(¬
` Context->AudioContext,¬
` NULL, /* no message, we've already unpacked it */¬
` &format¬
` );¬
`¬
` SOS_ASSERT_ASSUMPTION(¬
` format.SampleBits==16,¬
` "Currently only supports 16-bit audio resampling"¬
` );¬
`¬
` samples = Scale(avgDelta,format.Frequency,SOS_MSPERSECOND);¬
`
`Page 14 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 15/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`612
`613
`614
`615
`616
`617
`618
`619
`620
`621
`622
`623
`624
`625
`626
`627
`628
`629
`630
`631
`632
`633
`634
`635
`636
`637
`638
`639
`640
`641
`642
`643
`644
`645
`646
`647
`648
`649
`650
`651
`652
`653
`654
`655
`656
`
` samples /= Context->Param[PARAM_DAMPING]; /* dampen attack */¬
` quantum = (format.SampleBits+SOS_BITSPERBYTE-1)/¬
` SOS_BITSPERBYTE * format.Channels;¬
` bytes = samples * quantum;¬
`¬
`¬
`/* SOS_Debug_StringPrint(¬
` "Error is %lu samples, %lu bytes\n",¬
` samples,¬
` bytes¬
` );¬
`*/¬
` ¬
` if (bytes>0) {¬
`¬
` if (avgLate > Context->Param[PARAM_LATE_DROP]) {¬
` /*¬
` * Data is very late, drop it¬
` */¬
`¬
` SOS_DEBUGOUT_DETAIL("Audiosync trimming late packet\n");¬
`¬
` SOS_Message_HeadDataPop(¬
` Message,¬
` bytes,¬
` NULL,¬
` NULL¬
` );¬
`¬
` {// REVISIT - try silencing the fragment¬
` AudioSync_MessageFill(Message, 0);¬
` }¬
` } else if (avgEarly > Context->Param[PARAM_EARLY_COPY]) {¬
` /*¬
` * Data is very early, duplicate it enough to¬
` * fill the gap.¬
` */¬
` size_t length = SOS_Message_LengthGet(Message);¬
` ¬
` SOS_DEBUGOUT_DETAIL("Audiosync copying late packet\n");¬
` ¬
` while (bytes>0) {¬
` SOS_MESSAGE *append;¬
` size_t take = (bytes < length ? bytes : length);¬
` SOS_Message_HeadMessageCopyFrom(¬
`
`Page 15 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 16/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`657
`658
`659
`660
`661
`662
`663
`664
`665
`666
`667
`668
`669
`670
`671
`672
`673
`674
`675
`676
`677
`678
`679
`680
`681
`682
`683
`…
`684
`…
`685
`686
`687
`688
`689
`690
`691
`…
`692
`…
`693
`…
`694
`695
`696
`
` Message,¬
` take,¬
` &append¬
` );¬
` SOS_Message_TailMessagePush(¬
` Message,¬
` append¬
` );¬
` bytes-=take;¬
` }¬
` ¬
` {// REVISIT - try silencing the fragment¬
` AudioSync_MessageFill(Message, 0);¬
` }¬
` ¬
` } else {¬
` /*¬
` * Data is not quite on time, resample the input¬
` * buffer (up to a 1%) towards the correct values.¬
` */¬
`¬
` size_t length = SOS_Message_LengthGet(Message);¬
` size_t inSamples = length / sizeof(SOS_INT32);¬
` size_t outSamples;¬
`¬
` if (avgEarly>0) {¬
` size_t maxOutSamples =
`inSamples*Context->Param[PARAM_MAX_RESAMPLE_PERCENT]/100;¬
` SOS_DEBUGOUT_DETAIL("Audiosync resampling early
`packet\n");¬
` ¬
` outSamples = samples+inSamples;¬
` if (outSamples>maxOutSamples) {¬
` outSamples=maxOutSamples;¬
` }¬
` } else {¬
` size_t minOutSamples =
`inSamples*Context->Param[PARAM_MIN_RESAMPLE_PERCENT]/100;¬
` SOS_DEBUGOUT_DETAIL("Audiosync resampling late
`packet\n");¬
` outSamples = samples>inSamples ? 0 :
`inSamples-samples;¬
` if (outSamples<minOutSamples) {¬
` outSamples=minOutSamples;¬
` }¬
`
`Page 16 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 17/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`697
`698
`699
`700
`701
`702
`703
`704
`705
`706
`707
`708
`709
`710
`711
`712
`713
`714
`715
`716
`717
`718
`719
`720
`721
`722
`723
`724
`725
`726
`727
`728
`729
`730
`731
`732
`733
`734
`735
`736
`737
`…
`738
`739
`740
`
` }¬
`¬
` SOS_DEBUGOUT_DETAIL(¬
` "inSamples=%ld, outSamples=%lu\n",¬
` inSamples,¬
` outSamples¬
` );¬
` {¬
` SOS_INT32 *inBuffer = SOS_Mem_Alloc(length);¬
` SOS_INT32 *outBuffer;¬
` SOS_Message_HeadDataPop(¬
` Message,¬
` length,¬
` inBuffer,¬
` NULL¬
` );¬
` outBuffer = AudioSync_Resample16(¬
` inBuffer,¬
` inSamples,¬
` outSamples¬
` );¬
` ¬
` SOS_Message_HeadDataPush(¬
` Message,¬
` outBuffer,¬
` outSamples * sizeof(SOS_INT32),¬
` SOS_Mem_Free¬
` );¬
` SOS_Mem_Free(inBuffer);¬
` }¬
` }¬
` ¬
`#if 0¬
` // USE SILENCE TO FILL THE GAP¬
` // No longer used, but¬
` // REVISIT - might be good to start with silence¬
` // for first couple of packets?¬
`¬
` {¬
` void *data = SOS_Mem_Alloc(bytes);¬
`// SOS_Debug_StringPrint("Inserting %ld
`bytes\n",bytes);¬
` SOS_memset(¬
` data,¬
` format.SampleBits>8 ? 0x00 : 0x7F,¬
`
`Page 17 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 18/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`741
`742
`743
`744
`745
`746
`747
`748
`749
`750
`751
`752
`753
`754
`755
`756
`757
`758
`759
`760
`761
`762
`763
`…
`764
`765
`…
`766
`767
`768
`769
`770
`771
`772
`773
`774
`775
`776
`777
`778
`779
`780
`781
`782
`783
`
` bytes¬
` );¬
` SOS_Message_HeadDataPush(¬
` Message,¬
` data,¬
` bytes,¬
` SOS_Mem_Free¬
` );¬
` }¬
`#endif¬
` }¬
` ¬
` Context->AudioContext->Pack(¬
` Context->AudioContext,¬
` Message¬
` );¬
` }¬
`¬
` return status;¬
`}¬
`¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Bead Definition¬
`-------------------------------------------------------------------------
`----*/¬
`¬
`static¬
`SOS_STATUS¬
`AudioSync_MessageHandler(¬
` SOS_PATH *Path,¬
` SOS_MESSAGE *Message¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` AUDIOSYNC_CONTEXT *context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_MessageHandler\n");¬
`¬
` SOS_Path_SessionContextPeek(Path, (void**)&context);¬
`¬
` if (!context->ContextReady) {¬
` status = AudioSync_ContextPrepare(context, Path);¬
` if (SOS_SUCCEEDED(status)) {¬
`
`Page 18 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 19/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`784
`785
`786
`787
`788
`789
`790
`791
`792
`793
`794
`795
`796
`797
`798
`799
`800
`801
`802
`803
`804
`805
`…
`806
`807
`808
`809
`810
`811
`812
`813
`814
`815
`…
`816
`817
`818
`…
`819
`820
`821
`822
`823
`824
`825
`
` context->ContextReady = SOS_True;¬
` }¬
` }¬
`¬
` if (!context->ContextReady) {¬
` SOS_DEBUGOUT_DETAIL("AudioSync context is not ready");¬
` }¬
`¬
` if (context->ContextReady) {¬
` SOS_CLOCK_TICK masterEpoch;¬
` SOS_CLOCK_TICK renderEpoch;¬
` ¬
` if (SOS_SUCCEEDED(context->RenderClock->EpochGet(¬
` context->RenderClock,¬
` &renderEpoch))) {¬
`// SOS_Debug_StringPrint("Now = %lu\n",SOS_Clock_TickGet());¬
`// SOS_Debug_StringPrint("Render epoch = %lu\n",renderEpoch);¬
` ¬
` if (SOS_SUCCEEDED(context->MasterClock->EpochGet(¬
` context->MasterClock,¬
` &masterEpoch))) {¬
`// SOS_Debug_StringPrint("Master epoch =
`%lu\n",masterEpoch);¬
`¬
` status = AudioSync_Adjust(¬
` context,¬
` Path,¬
` Message,¬
` masterEpoch,¬
` renderEpoch¬
` );¬
` } else {¬
` SOS_DEBUGOUT_DETAIL("Master clock %p not
`set\n",context->MasterClock->Interface.Object);¬
` }¬
` } else {¬
` SOS_DEBUGOUT_DETAIL("Render clock %p not
`set\n",context->RenderClock->Interface.Object);¬
` }¬
` }¬
`¬
` /*¬
` * We will silence the first packet if:¬
` * we have an audio context unless¬
` * we can determine that the sample and master clocks are¬
`
`Page 19 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 20/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`826
`827
`828
`829
`830
`831
`832
`833
`834
`835
`836
`837
`838
`839
`840
`841
`842
`843
`844
`845
`846
`847
`848
`849
`850
`851
`852
`853
`854
`855
`856
`857
`858
`859
`860
`861
`862
`863
`864
`865
`866
`867
`868
`869
`870
`
` * the same object. This ensures that when this bead¬
` * is put in a master stream it doesn't silence the¬
` * first packet.¬
` */¬
` ¬
` if (context->First &&¬
` context->AudioContext &&¬
` (¬
` !context->MasterClock ||¬
` !context->RenderClock ||¬
` (¬
` SOS_Interface_ObjectPeek(context->MasterClock) !=¬
` SOS_Interface_ObjectPeek(context->RenderClock)¬
` )¬
` )¬
` ) {¬
` context->AudioContext->Unpack(¬
` context->AudioContext,¬
` Message¬
` );¬
`¬
` /*¬
` * if it fails to fill the message it¬
` * leaves the message intact, and we return¬
` * the status which causes the message to¬
` * be discarded ultimately (which is fine)¬
` */¬
` status = AudioSync_MessageFill(Message, 0);¬
` ¬
` context->AudioContext->Pack(¬
` context->AudioContext,¬
` Message¬
` );¬
`context->First = SOS_False;¬
` }¬
`¬
` if (SOS_SUCCEEDED(status)) {¬
` SOS_Path_MessageSend(Path, Message);¬
` } else {¬
` SOS_Message_Destroy(Message);¬
` }¬
`¬
` return status;¬
`}¬
`¬
`
`Page 20 of 25
`
`Implicit Exhibit 2084
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/audiosync.c
`Page 21/25
`Saved: 11/9/01, 6:53:11 PM
`Printed for: Implicit
`
`871
`872
`873
`874
`875
`876
`877
`878
`879
`880
`881
`882
`883
`884
`885
`886
`887
`888
`889
`890
`891
`892
`893
`…
`894
`895
`896
`897
`898
`899
`900
`901
`902
`903
`904
`905
`906
`907
`908
`909
`910
`911
`912
`913
`914
`
`static¬
`SOS_STATUS¬
`AudioSync_PrerollHandler(¬
` SOS_PATH *Path,¬
` SOS_MESSAGE *Message¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` AUDIOSYNC_CONTEXT *context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("AudioSync_PrerollHandler\n");¬
`¬
` SOS_Path_SessionContextPeek(Path, (void**)&context);¬
`¬
` if (!context->AudioContext) {¬
` AudioContextGet(¬
` Path,¬
` SOS_AUDIOCONTEXT_NAME,¬
` &context->AudioContext¬
` );¬
` }¬
`¬
` SOS_ASSERT_ASSUMPTION(context->AudioContext, "Didn't find audio
`context");¬
`¬
` if (context->AudioContext) {¬
` if (context->First) {¬
`