Logo Search packages:      
Sourcecode: wavpack version File versions  Download package

pack.c

////////////////////////////////////////////////////////////////////////////
//                           **** WAVPACK ****                            //
//                  Hybrid Lossless Wavefile Compressor                   //
//              Copyright (c) 1998 - 2006 Conifer Software.               //
//               MMX optimizations (c) 2006 Joachim Henke                 //
//                          All Rights Reserved.                          //
//      Distributed under the BSD Software License (see license.txt)      //
////////////////////////////////////////////////////////////////////////////

// pack.c

// This module actually handles the compression of the audio data, except for
// the entropy coding which is handled by the words? modules. For efficiency,
// the conversion is isolated to tight loops that handle an entire buffer.

#include "wavpack_local.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#ifdef DEBUG_ALLOC
#define malloc malloc_db
#define realloc realloc_db
#define free free_db
void *malloc_db (uint32_t size);
void *realloc_db (void *ptr, uint32_t size);
void free_db (void *ptr);
int32_t dump_alloc (void);
#endif

//////////////////////////////// local tables ///////////////////////////////

// These two tables specify the characteristics of the decorrelation filters.
// Each term represents one layer of the sequential filter, where positive
// values indicate the relative sample involved from the same channel (1=prev),
// 17 & 18 are special functions using the previous 2 samples, and negative
// values indicate cross channel decorrelation (in stereo only).

static WavpackDecorrSpec fast_specs [] = {
        { 1, 2,18,17 },  // 0
        { 1, 1,17,17 },  // 1
        { 0, 2,18,17 },  // 2
        { 0, 1,17,17 },  // 3
        { 1, 3, 1,18 },  // 4
        { 1, 1,17, 1 },  // 5
        { 0, 1, 1,17 },  // 6
        { 0, 1,-2,17 },  // 7
        { 0, 2,-1,17 },  // 8
        { 1, 1,17, 2 },  // 9
        { 0, 3,18,18 },  // 10
        { 0, 1,17, 1 },  // 11
        { 1, 6, 1, 2 },  // 12
        { 1, 1,17, 3 },  // 13
        { 0, 1,-2, 3 },  // 14
        { 0, 1, 2,17 },  // 15
        { 0, 1,18,-2 },  // 16
        { 0, 1,-1,17 },  // 17
        { 0, 1,18,17 },  // 18
        { 0, 1,17, 2 },  // 19
        { 1, 2,18,-2 },  // 20
        { 1, 1, 1,17 },  // 21
        { 0, 3,18, 2 },  // 22
        { 0, 1,17,-2 },  // 23
        { 0, 1,18,-2 },  // 24
        { 1, 2,17,-3 },  // 25
        { 0, 1,18, 3 },  // 26
        { 0, 1,18,18 },  // 27
        { 1, 1, 1, 3 },  // 28
        { 1, 1,18, 3 },  // 29
        { 1, 1, 1, 3 },  // 30
        { 0, 2,18,17 },  // 31
        { 1, 1, 1,17 },  // 32
        { 1, 1,17, 3 },  // 33
        { 0, 3,18,17 },  // 34
        { 0, 1,18,18 },  // 35
        { 1, 1, 1, 3 },  // 36
        { 1, 1, 1,18 },  // 37
        { 0, 1,18,-2 },  // 38
        { 0, 2,18,17 },  // 39
        { 0, 1,-1,18 },  // 40
        { 1, 1,17, 3 },  // 41
        { 0, 1,17, 2 },  // 42
        { 0, 1,17, 3 },  // 43
        { 1, 1,18, 2 },  // 44
        { 1, 1,17,-2 },  // 45
        { 0, 1, 1,-2 },  // 46
        { 0, 2,18,17 },  // 47
        { 0, 1,17,-2 },  // 48
        { 1, 1,17,-2 },  // 49
        { 0, 1,18, 3 },  // 50
        { 0, 1, 2,17 },  // 51
        { 1, 2,18,-3 },  // 52
        { 1, 2, 1,18 },  // 53
        { 1, 2,18, 2 },  // 54
        { 0, 1,17,-1 },  // 55
        { 0, 1,17,-2 },  // 56
        { 1, 1,17,-2 },  // 57
        { 1, 1, 1, 3 },  // 58
        { 0, 1, 1,17 },  // 59
        { 1, 2,18,-2 },  // 60
        { 1, 2,17,-3 },  // 61
        { 0, 2,18,17 },  // 62
        { 0, 2,18,17 },  // 63
        { 1, 1,17, 2 },  // 64
        { 1, 2,18,18 },  // 65
        { 0, 1,17, 2 },  // 66
        { 0, 1,18,17 },  // 67
        { 1, 1, 1,17 },  // 68
        { 1, 1,17, 2 },  // 69
        { 0, 2,18,18 },  // 70
        { 0, 2,18,17 },  // 71
        { 1, 2,17,-3 },  // 72
        { 1, 6, 1, 2 },  // 73
        { 0, 3,17,17 },  // 74
        { 0, 1, 1,18 },  // 75
        { 0, 1, 1,-2 },  // 76
        { 1, 1,17, 2 },  // 77
        { 0, 2,18,17 },  // 78
        { 0, 2,18,17 },  // 79
        { 1, 1,18, 3 },  // 80
        { 1, 2,17,-3 },  // 81
        { 0, 1,17, 2 },  // 82
        { 0, 1,17, 3 },  // 83
        { 0, 1,18,-2 },  // 84
        { 1, 1,18,18 },  // 85
        { 1, 6, 1, 2 },  // 86
        { 0, 2,18,17 },  // 87
        { 0, 2,18,17 },  // 88
        { 0, 1,-1,17 },  // 89
        { 1, 1,18, 3 },  // 90
        { 0, 1,17,18 },  // 91
        { 1, 1,17, 3 },  // 92
        { 0, 1,18, 3 },  // 93
        { 0, 2,18,17 },  // 94
        { 0, 2,18,17 },  // 95
        { 1, 2,18, 2 },  // 96
        { 0, 1,-2, 3 },  // 97
        { 0, 4,18,-1 },  // 98
        { 0, 2,18,18 },  // 99
        { 0, 1,-2, 3 },  // 100
        { 1, 1,17,-2 },  // 101
        { 0, 1,17, 3 },  // 102
        { 0, 2,18,17 },  // 103
        { 0, 2,-1,18 },  // 104
        { 1, 1, 2,17 },  // 105
        { 0, 2,17,-2 },  // 106
        { 0, 1,17, 2 },  // 107
        { 1, 2,18,-3 },  // 108
        { 0, 1,17,-2 },  // 109
        { 0, 2,18,17 },  // 110
        { 0, 2,18,17 },  // 111
        { 1, 1,17,-2 },  // 112
        { 1, 2,17,-3 },  // 113
        { 1, 1, 1, 3 },  // 114
        { 1, 1, 2,17 },  // 115
        { 1, 2,18, 2 },  // 116
        { 1, 1, 2,17 },  // 117
        { 1, 1,18, 2 },  // 118
        { 0, 2,18,17 },  // 119
        { 0, 2,18,17 },  // 120
        { 0, 1,17,-2 },  // 121
        { 0, 2,18,17 },  // 122
        { 0, 2,17,-1 },  // 123
        { 0, 2,18,-2 },  // 124
        { 0, 2,18,17 },  // 125
        { 0, 2,18,17 },  // 126
        { 0, 2,18,17 },  // 127
        { 1, 1, 1, 3 },  // 128
        { 0, 2,-2,17 },  // 129
        { 0, 2,18,-2 },  // 130
        { 0, 2,17,-2 },  // 131
        { 1, 1, 2,17 },  // 132
        { 1, 1, 1, 3 },  // 133
        { 0, 1, 2,17 },  // 134
        { 0, 2,18,17 },  // 135
        { 0, 3,-1,17 },  // 136
        { 1, 1, 2,17 },  // 137
        { 0, 2,18,18 },  // 138
        { 0, 1,17, 2 },  // 139
        { 1, 4,18,-3 },  // 140
        { 1, 1,18, 1 },  // 141
        { 0, 2,18,17 },  // 142
        { 0, 2,18,17 },  // 143
        { 1, 2,18,-1 },  // 144
        { 0, 1,-1,18 },  // 145
        { 1, 6, 1, 2 },  // 146
        { 1, 1,17, 2 },  // 147
        { 1, 4,18, 3 },  // 148
        { 0, 1, 1,17 },  // 149
        { 0, 1,18, 2 },  // 150
        { 0, 2,18,17 },  // 151
        { 0, 2,18,17 },  // 152
        { 1, 2,17, 2 },  // 153
        { 0, 2,18,-2 },  // 154
        { 0, 1, 1,18 },  // 155
        { 1, 2,18,-3 },  // 156
        { 0, 2,18,17 },  // 157
        { 0, 2,18,17 },  // 158
        { 0, 2,18,17 },  // 159
        { 1, 2,18,18 },  // 160
        { 1, 3,17,17 },  // 161
        { 0, 1,-2,17 },  // 162
        { 0, 1,17,18 },  // 163
        { 0, 1,-1, 3 },  // 164
        { 1, 1, 2,17 },  // 165
        { 0, 2,18,-1 },  // 166
        { 0, 2,18,17 },  // 167
        { 0, 2,18,17 },  // 168
        { 1, 1,17,-2 },  // 169
        { 1, 2,17, 2 },  // 170
        { 1, 1,18, 3 },  // 171
        { 0, 1,18, 2 },  // 172
        { 1, 2,17,-3 },  // 173
        { 0, 2,18,17 },  // 174
        { 0, 2,18,17 },  // 175
        { 0, 1,-2,17 },  // 176
        { 0, 1,17,-1 },  // 177
        { 0, 1,18,-1 },  // 178
        { 0, 2,18,17 },  // 179
        { 1, 2,17,-3 },  // 180
        { 1, 1, 1,18 },  // 181
        { 1, 3,18, 2 },  // 182
        { 0, 2,18,17 },  // 183
        { 0, 2,18,17 },  // 184
        { 0, 2,18,17 },  // 185
        { 0, 2,18,17 },  // 186
        { 0, 3,18,18 },  // 187
        { 0, 1, 1,-2 },  // 188
        { 0, 2,18,17 },  // 189
        { 0, 2,18,17 },  // 190
        { 0, 2,18,17 },  // 191
        { 1, 2,17,-3 },  // 192
        { 1, 1,18,18 },  // 193
        { 0, 2,18, 2 },  // 194
        { 0, 1,17,18 },  // 195
        { 1, 2,18, 2 },  // 196
        { 1, 1,17,-2 },  // 197
        { 0, 2,17,-1 },  // 198
        { 0, 2,18,17 },  // 199
        { 0, 2,18,17 },  // 200
        { 0, 2,18,17 },  // 201
        { 0, 1, 1,-2 },  // 202
        { 0, 1,18, 1 },  // 203
        { 1, 2,18,-2 },  // 204
        { 0, 1,17, 2 },  // 205
        { 0, 2,18,17 },  // 206
        { 0, 2,18,17 },  // 207
        { 1, 1,17, 3 },  // 208
        { 0, 1,17,-1 },  // 209
        { 0, 1,18, 2 },  // 210
        { 1, 1,17, 3 },  // 211
        { 1, 1,17,-2 },  // 212
        { 0, 1,18,18 },  // 213
        { 0, 2,18,17 },  // 214
        { 0, 2,18,17 },  // 215
        { 0, 2,18,17 },  // 216
        { 0, 2,18,17 },  // 217
        { 0, 2,18,17 },  // 218
        { 1, 1,17,18 },  // 219
        { 0, 1,-2, 3 },  // 220
        { 0, 2,18,17 },  // 221
        { 0, 2,18,17 },  // 222
        { 0, 2,18,17 },  // 223
        { 1, 2,18,-3 },  // 224
        { 0, 2,18,17 },  // 225
        { 0, 3,18, 2 },  // 226
        { 0, 1, 1,18 },  // 227
        { 0, 2,18,17 },  // 228
        { 0, 1,17,-1 },  // 229
        { 0, 2,18,17 },  // 230
        { 0, 2,18,17 },  // 231
        { 0, 2,18,17 },  // 232
        { 0, 1,-2, 3 },  // 233
        { 0, 3,17,17 },  // 234
        { 0, 2,18,17 },  // 235
        { 0, 2,18,17 },  // 236
        { 1, 1,17, 2 },  // 237
        { 0, 2,18,17 },  // 238
        { 0, 2,18,17 },  // 239
        { 1, 1,17, 2 },  // 240
        { 0, 2,18,17 },  // 241
        { 0, 2,18,17 },  // 242
        { 0, 2,18,17 },  // 243
        { 0, 2,18, 2 },  // 244
        { 0, 2,18,17 },  // 245
        { 0, 2,18,17 },  // 246
        { 0, 2,18,17 },  // 247
        { 0, 2,18,17 },  // 248
        { 0, 2,18,17 },  // 249
        { 0, 2,18,17 },  // 250
        { 0, 2,18,17 },  // 251
        { 0, 2,18,17 },  // 252
        { 0, 2,18,17 },  // 253
        { 0, 2,18,17 },  // 254
        { 0, 2,18,17 },  // 255
};

static WavpackDecorrSpec default_specs [] = {
        { 1, 2,18,18, 2,17, 3 },         // 0
        { 0, 2,18,17,-1, 3, 2 },         // 1
        { 1, 1,17,18,18,-2, 2 },         // 2
        { 0, 2,18,17, 3,-2,17 },         // 3
        { 1, 2,18,17, 2,17, 3 },         // 4
        { 0, 1,18,18,-1, 2,17 },         // 5
        { 0, 1,17,17,-2, 2, 3 },         // 6
        { 0, 1,18,-2,18, 2,17 },         // 7
        { 1, 2,18,18,-1, 2, 3 },         // 8
        { 0, 2,18,17, 3, 2, 5 },         // 9
        { 1, 1,18,17,18, 2, 5 },         // 10
        { 0, 1,17,17,-2, 2, 3 },         // 11
        { 0, 1,18,-2,18, 2, 5 },         // 12
        { 0, 1,17,-2,17, 2,-3 },         // 13
        { 1, 1,17,-2,17, 1, 2 },         // 14
        { 0, 1,17,17,-2, 2, 3 },         // 15
        { 1, 1,18, 3, 1, 5, 4 },         // 16
        { 1, 4,18,18, 2, 3,-2 },         // 17
        { 0, 1, 1,-1,-1, 2,17 },         // 18
        { 0, 2,18,17, 3, 2, 5 },         // 19
        { 0, 1,18,18,18, 2,17 },         // 20
        { 0, 1,18,17,-1, 2,18 },         // 21
        { 1, 1,17, 3, 2, 1, 7 },         // 22
        { 0, 2,18,-2,18, 2, 3 },         // 23
        { 1, 3,18,-3,18, 2, 3 },         // 24
        { 0, 3,18,17, 2, 3,17 },         // 25
        { 1, 1,17,17, 2, 1, 4 },         // 26
        { 0, 1,17,18,-2, 2,17 },         // 27
        { 1, 1,18,18, 3, 5, 2 },         // 28
        { 0, 1,17,17, 2,18, 4 },         // 29
        { 0, 1,18,17, 1, 4, 6 },         // 30
        { 1, 1, 3,17,18, 2,17 },         // 31
        { 1, 1,17, 3, 2, 1, 7 },         // 32
        { 0, 1,18,17,-1, 2, 3 },         // 33
        { 1, 1,17,17, 2, 1, 4 },         // 34
        { 1, 2,18,17,-1,17, 3 },         // 35
        { 1, 2,18,17, 2, 3,-1 },         // 36
        { 0, 2,18,18,-2, 2,17 },         // 37
        { 0, 1,17,17, 2,18, 4 },         // 38
        { 0, 5,-2,18,18,18, 2 },         // 39
        { 1, 1,18,18,-1, 6, 3 },         // 40
        { 0, 1,17,17,-2, 2, 3 },         // 41
        { 1, 1,18,17,18, 2,17 },         // 42
        { 0, 1,18,17, 4, 3, 1 },         // 43
        { 0, 1,-2,18, 2, 2,18 },         // 44
        { 1, 2,18,18,-2, 2,-1 },         // 45
        { 1, 1,17,17, 2, 1, 4 },         // 46
        { 0, 1,17,18,-2, 2,17 },         // 47
        { 1, 1,17, 3, 2, 1, 7 },         // 48
        { 1, 3,18,-3,18, 2, 3 },         // 49
        { 1, 2,18,18,-2, 2,-1 },         // 50
        { 1, 1,18,18, 3, 5, 2 },         // 51
        { 0, 2,18,18,-1, 2,17 },         // 52
        { 0, 1,18,-1,17,18, 2 },         // 53
        { 0, 1,17,-1, 2, 3, 6 },         // 54
        { 0, 1,18,-2,18, 2, 5 },         // 55
        { 1, 2,18,18,-2, 2,-1 },         // 56
        { 0, 3,18,18, 2, 3,17 },         // 57
        { 0, 1,17,17, 2,18, 4 },         // 58
        { 1, 1,17,-2,17, 1, 2 },         // 59
        { 0, 1,-1, 3, 5, 4, 7 },         // 60
        { 0, 3,18,18, 3, 2, 5 },         // 61
        { 0, 1,17,17, 2,18, 4 },         // 62
        { 0, 1,18,17,-2,18, 3 },         // 63
        { 0, 2,18,18,-2, 2,17 },         // 64
        { 0, 3,18,17,-2, 2, 3 },         // 65
        { 1, 1,18,18,-2, 2,17 },         // 66
        { 0, 1,18,17, 4, 3, 1 },         // 67
        { 1, 2, 3,18,17, 2,17 },         // 68
        { 1, 2,18,18, 2,-2,18 },         // 69
        { 1, 2,18,18,-1,18, 2 },         // 70
        { 0, 2,18,18,-2, 2,17 },         // 71
        { 1, 3,18,18, 2, 3,-2 },         // 72
        { 0, 3,18,18, 3, 2, 5 },         // 73
        { 0, 1,18,-2,18, 2, 5 },         // 74
        { 1, 1,17, 3, 2, 1, 7 },         // 75
        { 1, 3,18,18,-2, 2,18 },         // 76
        { 1, 1,17,18,18,-2, 2 },         // 77
        { 0, 1,18,-2,18, 2, 5 },         // 78
        { 0, 2,18,-2,18, 2, 3 },         // 79
        { 0, 1,-1, 3, 4, 5, 7 },         // 80
        { 1, 1,17,17, 2,-1, 7 },         // 81
        { 0, 1,18,-1,-1, 2,-2 },         // 82
        { 0, 2,18,17, 2, 3,17 },         // 83
        { 0, 1,18,17, 2,18, 2 },         // 84
        { 0, 2,18,17,-1, 2,17 },         // 85
        { 0, 1, 1,18, 3, 2, 5 },         // 86
        { 0, 2,18,-2, 4,18, 2 },         // 87
        { 1, 1,18, 3, 1, 5, 4 },         // 88
        { 0, 1,18,17,18, 2, 5 },         // 89
        { 1, 1,18, 3, 1, 5, 4 },         // 90
        { 0, 4,18,18,-2, 2,18 },         // 91
        { 1, 1,18,18, 3, 2, 5 },         // 92
        { 1, 1,17,17, 2, 1, 4 },         // 93
        { 0, 2,18,18,-2,18, 2 },         // 94
        { 0, 2,18,18,-2,18, 2 },         // 95
        { 1, 1,18,18, 2, 1, 3 },         // 96
        { 1, 1,17,17, 2, 1, 4 },         // 97
        { 1, 2,17,17, 2,18, 3 },         // 98
        { 0, 1,18,17, 1, 4, 6 },         // 99
        { 1, 2,18,18,-2, 2,-1 },         // 100
        { 0, 1,18,-2,18, 2, 5 },         // 101
        { 1, 1,17, 2,18, 2,17 },         // 102
        { 0, 2,18,18,-2,18, 2 },         // 103
        { 0, 1,18,18, 3, 6,-1 },         // 104
        { 0, 1,18,17, 2,18, 3 },         // 105
        { 0, 1,18,17,-2, 2,17 },         // 106
        { 1, 1, 3,17,18, 2,17 },         // 107
        { 1, 3,18,-3,18, 2, 3 },         // 108
        { 1, 3,18,18,-3,18, 2 },         // 109
        { 1, 1,18, 3, 1, 5, 4 },         // 110
        { 0, 1,17,-2,17, 2,-3 },         // 111
        { 1, 1,18,18, 3, 5, 2 },         // 112
        { 1, 2,18,18,-2, 2,-1 },         // 113
        { 0, 1,18,-1,-1, 2,-2 },         // 114
        { 1, 1,18, 3, 1, 5, 4 },         // 115
        { 0, 3,18,17,-1, 2,17 },         // 116
        { 1, 3,18,17, 2,18,-2 },         // 117
        { 0, 2,18,18,-2,18, 2 },         // 118
        { 1, 2,18,18,-2, 2,-1 },         // 119
        { 1, 1,18, 3, 1, 5, 4 },         // 120
        { 0, 4, 3,18,18, 2,17 },         // 121
        { 0, 2,18,18,-2,18, 2 },         // 122
        { 1, 1,18,17,-1,18, 2 },         // 123
        { 0, 2,18,18,-2,18, 2 },         // 124
        { 0, 2,18,18,-2,18, 2 },         // 125
        { 0, 2,18,18,-2,18, 2 },         // 126
        { 0, 2,18,18,-2,18, 2 },         // 127
        { 1, 1,18,18,18, 3, 2 },         // 128
        { 0, 1,17,-1, 2, 3, 6 },         // 129
        { 0, 1,17,-1, 2, 3, 6 },         // 130
        { 0, 2,18,17,-2, 3, 2 },         // 131
        { 1, 3,18,17, 2,-2,18 },         // 132
        { 0, 2,18,18, 2,17, 3 },         // 133
        { 0, 1,18,18, 2,18,-2 },         // 134
        { 0, 2,18,-2, 4,18, 2 },         // 135
        { 0, 1,-2,18, 2, 2,18 },         // 136
        { 0, 2,18,17, 3, 6, 2 },         // 137
        { 0, 1,18,17,18, 2, 5 },         // 138
        { 0, 3,18,18,-2, 3, 2 },         // 139
        { 1, 1,18,18, 2,18, 5 },         // 140
        { 0, 1,17,-1, 2, 3, 6 },         // 141
        { 1, 4,18,18, 2, 3,-2 },         // 142
        { 0, 2,18,17,18, 2,-2 },         // 143
        { 0, 1, 1,18, 3, 2, 5 },         // 144
        { 1, 4,18,-2,18, 2, 3 },         // 145
        { 1, 2,18, 2,18, 3,-2 },         // 146
        { 0, 2,18,18,18, 2, 4 },         // 147
        { 0, 2, 3,17,18, 2,17 },         // 148
        { 1, 1,18,-1,18, 2,17 },         // 149
        { 1, 2,17,17, 2,18, 3 },         // 150
        { 0, 2,18,17,-2, 3, 2 },         // 151
        { 0, 1, 1,-1,-1, 2,17 },         // 152
        { 0, 3, 3,18,18, 2,17 },         // 153
        { 0, 1,18,-1,17,18, 2 },         // 154
        { 0, 1,18,17, 2,18, 3 },         // 155
        { 0, 2,18,18,-2,18, 2 },         // 156
        { 0, 1,18,17, 2,18, 2 },         // 157
        { 0, 2,18,18,-2,18, 2 },         // 158
        { 0, 2,18,18,-2,18, 2 },         // 159
        { 1, 2,17,17, 2,18, 3 },         // 160
        { 0, 1,18,17,-2, 2, 3 },         // 161
        { 0, 1,18,-2,18, 2, 5 },         // 162
        { 1, 4,18,-2,18, 2, 3 },         // 163
        { 1, 3,18,17, 2, 3, 6 },         // 164
        { 0, 2,18,18, 2,17, 3 },         // 165
        { 0, 2,18,17, 2,18, 2 },         // 166
        { 0, 2,18,18,-2,18, 2 },         // 167
        { 1, 1,18,18, 3, 5, 2 },         // 168
        { 0, 2,18,18,-2, 2, 3 },         // 169
        { 1, 2,18,17, 2,17, 3 },         // 170
        { 0, 1,18,17, 2, 3,18 },         // 171
        { 0, 2,18,18,-2,18, 2 },         // 172
        { 1, 4,18,18, 2, 3,-2 },         // 173
        { 0, 1,17,-2,17, 2,-3 },         // 174
        { 0, 1,17,17, 2,18, 4 },         // 175
        { 1, 1,18,18,18, 2, 4 },         // 176
        { 1, 2,18, 2,18, 3,-2 },         // 177
        { 1, 1,18,18,-2, 2,17 },         // 178
        { 0, 2,18,18,-2,18, 2 },         // 179
        { 0, 2,18,18, 2,17, 3 },         // 180
        { 0, 2,18,18,18, 2, 4 },         // 181
        { 0, 2,18,18,-2,18, 2 },         // 182
        { 0, 2,18,17,-2, 3, 2 },         // 183
        { 0, 1, 1,-1,-1, 2,17 },         // 184
        { 1, 4,18,18, 2, 3,-2 },         // 185
        { 0, 2,18,18,-2,18, 2 },         // 186
        { 0, 1,18,-2,18, 3, 2 },         // 187
        { 0, 2,18,18,-2,18, 2 },         // 188
        { 0, 2,18,18,-2,18, 2 },         // 189
        { 0, 2,18,18,-2,18, 2 },         // 190
        { 0, 2,18,18,-2,18, 2 },         // 191
        { 0, 1,18,18,-2, 2,17 },         // 192
        { 0, 3,18,17, 2, 3,17 },         // 193
        { 1, 2,18,18, 2,-2,18 },         // 194
        { 0, 1,-1, 3, 5, 4, 7 },         // 195
        { 1, 1,18, 3, 1, 5, 4 },         // 196
        { 1, 1,18,18,-2,18, 3 },         // 197
        { 0, 2,18,17,18, 2,-2 },         // 198
        { 0, 2,18,18, 2,17, 3 },         // 199
        { 1, 2,18, 2,18, 3,-2 },         // 200
        { 1, 4,18,18, 2, 3,-2 },         // 201
        { 1, 3,18,17, 2, 3, 6 },         // 202
        { 0, 2,18,18,-2,18, 2 },         // 203
        { 1, 2,18,17,-2,-1,17 },         // 204
        { 0, 1,17,-1, 2, 3, 6 },         // 205
        { 0, 2,18,18,-2,18, 2 },         // 206
        { 0, 2,18,18,-2, 2, 3 },         // 207
        { 1, 1,18,18,18, 2, 5 },         // 208
        { 0, 1,17,17,-2, 2, 3 },         // 209
        { 0, 2,18,18,-2,18, 2 },         // 210
        { 0, 2,18,17, 3, 6, 2 },         // 211
        { 0, 2,18,17,18, 2, 3 },         // 212
        { 0, 3,18,17,-3,18, 2 },         // 213
        { 0, 1,18,18,18, 2, 3 },         // 214
        { 0, 1,18,-2,-3, 2, 6 },         // 215
        { 0, 2,18,18,-2,18, 2 },         // 216
        { 1, 1,18,17,18, 2, 5 },         // 217
        { 0, 2,18,18,-2,18, 2 },         // 218
        { 0, 2,18,18,-2,18, 2 },         // 219
        { 1, 1,18,17,18, 2, 5 },         // 220
        { 0, 2,18,18,-2,18, 2 },         // 221
        { 0, 2,18,18,-2,18, 2 },         // 222
        { 0, 2,18,18,-2,18, 2 },         // 223
        { 0, 1,18,18,18, 2, 3 },         // 224
        { 1, 1,17,-2,17, 1, 2 },         // 225
        { 1, 1,17,17, 2,-1, 7 },         // 226
        { 0, 1,18,17, 4, 3, 1 },         // 227
        { 1, 3,18,-3,18, 2, 3 },         // 228
        { 0, 1, 1,18, 3, 2, 5 },         // 229
        { 0, 2,18,18,-2,18, 2 },         // 230
        { 0, 2,18,18,-2,18, 2 },         // 231
        { 0, 1,18,18, 3, 6, 2 },         // 232
        { 0, 1,17,17, 2,18, 4 },         // 233
        { 0, 1,17,17, 2,18, 4 },         // 234
        { 0, 2,18,18,-2,18, 2 },         // 235
        { 0, 2,18,18,-2,18, 2 },         // 236
        { 0, 2,18,18,-2,18, 2 },         // 237
        { 1, 2,18,-2,18, 3, 2 },         // 238
        { 1, 1,17,-2,17, 1, 2 },         // 239
        { 1, 1,18,18, 3, 2, 5 },         // 240
        { 0, 1,18,18,-1, 2, 3 },         // 241
        { 0, 2,18,18,-2,18, 2 },         // 242
        { 0, 2,18,18,-2,18, 2 },         // 243
        { 0, 1,18,17,18, 2, 5 },         // 244
        { 0, 2,18,18,-2,18, 2 },         // 245
        { 0, 2,18,18,-2,18, 2 },         // 246
        { 0, 2,18,18,-2,18, 2 },         // 247
        { 0, 2,18,18,-2,18, 2 },         // 248
        { 0, 1, 3,18,18, 2,17 },         // 249
        { 0, 2,18,18,-2,18, 2 },         // 250
        { 0, 2,18,18,-2,18, 2 },         // 251
        { 0, 2,18,18,-2,18, 2 },         // 252
        { 0, 2,18,18,-2,18, 2 },         // 253
        { 0, 2,18,18,-2,18, 2 },         // 254
        { 0, 2,18,18,-2,18, 2 },         // 255
};

static WavpackDecorrSpec high_specs [] = {
        { 1, 2,18,18,18,-2, 2, 3, 5,-1,17, 4 },  // 0
        { 0, 1,18,17,-2, 2,18, 3, 7, 2, 5, 4 },  // 1
        { 1, 2, 1,18, 3, 6,-2,18, 2, 3, 4, 5 },  // 2
        { 0, 2,18,18,-2, 2,18, 3, 6, 2,17, 4 },  // 3
        { 1, 2,18,18, 2,18, 3, 2,-1, 4,18, 5 },  // 4
        { 1, 1, 7, 6, 5, 3, 4, 2, 5, 4, 3, 7 },  // 5
        { 1, 1,17, 3,18, 7, 2, 6, 1, 4, 3, 5 },  // 6
        { 1, 1,-2,18,18,18, 3,-2, 6, 5, 2, 1 },  // 7
        { 1, 2,18,18,-1,18, 2, 3, 6,-2,17, 5 },  // 8
        { 0, 1,17,17,18, 3, 6, 4, 5, 2,18,-2 },  // 9
        { 1, 2, 1,18,-2, 3, 5, 2, 4,-1, 6, 1 },  // 10
        { 0, 2,18,18, 3, 6,18, 2, 4, 8, 5, 3 },  // 11
        { 0, 1,-2, 1,18, 2,-2, 7,18, 2,-1, 5 },  // 12
        { 1, 1, 4, 3, 8, 1, 5, 2, 5, 6, 2, 8 },  // 13
        { 1, 1,17,18, 2, 6, 3, 4,-1, 1, 8, 6 },  // 14
        { 0, 1,18,18, 3, 6, 3,-2, 2, 5,-1, 1 },  // 15
        { 0, 1,18,18,17,-1, 2,-2,18, 3, 4, 5 },  // 16
        { 1, 2,18,17, 2,-2,18, 3, 5, 7, 2, 4 },  // 17
        { 1, 2,18,18, 3, 6,-2,18, 2, 5, 8, 3 },  // 18
        { 0, 1,18,17, 2,18,18, 2, 6, 5,17, 7 },  // 19
        { 1, 2,18,17, 2,18, 3, 2, 6,18,-1, 4 },  // 20
        { 1, 1, 5, 3, 6, 5, 3, 4, 1, 2, 4, 7 },  // 21
        { 1, 1, 5, 3, 6, 5, 3, 4, 1, 2, 4, 7 },  // 22
        { 0, 1,-2,18,18,18,-2, 3, 2, 4, 6, 5 },  // 23
        { 1, 2,18,17,-3, 3,-1,18, 2, 3, 6, 5 },  // 24
        { 0, 1,17,18, 7, 3,-2, 7, 1, 2, 4, 5 },  // 25
        { 1, 1, 2,18,18,-2, 2, 4,-1,18, 3, 6 },  // 26
        { 0, 3, 1,18, 4, 3, 5, 2, 4,18, 2, 3 },  // 27
        { 0, 1,-2,18, 2,18, 3, 7,18, 2, 6,-2 },  // 28
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 29
        { 1, 1,18,18, 5, 4, 6, 4, 5, 1, 4, 3 },  // 30
        { 1, 1,18, 3, 6, 5, 7, 8, 2, 3, 1,-1 },  // 31
        { 1, 1,18,18,18, 2,-2, 3, 5,18, 2, 8 },  // 32
        { 0, 2,18,17,-2, 2, 3,18,-3, 5, 2, 7 },  // 33
        { 1, 1, 1, 1,-1, 8,17, 3,-2, 2, 6,17 },  // 34
        { 0, 2,18,18,17, 2,-2, 3, 2, 4,18, 5 },  // 35
        { 1, 1,17,18, 2,-1, 5, 7,18, 3, 4, 6 },  // 36
        { 1, 1, 5, 4, 5,17, 3, 6, 3, 4, 7, 2 },  // 37
        { 0, 1,17, 3, 1, 7, 4, 2, 5,-2,18, 6 },  // 38
        { 0, 1,17,18, 2,18, 4, 3, 5, 7,-3, 6 },  // 39
        { 1, 2,17,17,-3,-2, 2, 8,18,-1, 3, 5 },  // 40
        { 0, 1,17,17,18, 2, 3, 6,-2, 8, 1, 7 },  // 41
        { 1, 1, 1, 2, 6,-2,18, 2, 5,-3, 7,-2 },  // 42
        { 0, 1,18,18, 3,18, 6, 8,-2, 2, 3, 5 },  // 43
        { 0, 1,18,17, 2,18,-2, 3, 7, 6, 2, 4 },  // 44
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 45
        { 1, 1,18,18, 2,-1, 3, 6, 1, 3, 4, 8 },  // 46
        { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 },  // 47
        { 0, 1,18,17,-3,18, 2, 4,-2, 3, 6,17 },  // 48
        { 1, 3, 1, 2,17, 3,18, 7,-1, 5, 2, 4 },  // 49
        { 1, 1,18, 3,18, 6, 8,18,-2, 5, 7, 2 },  // 50
        { 0, 1,17, 2,18, 6, 3, 2, 5, 4, 8, 1 },  // 51
        { 0, 1,18,17,-1, 2, 3,18,18, 2, 3,17 },  // 52
        { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 4 },  // 53
        { 1, 1, 6,17, 3, 8, 1, 5, 7,-1, 2, 1 },  // 54
        { 1, 1,18,-2,18, 3,-2, 2, 7, 4, 6,18 },  // 55
        { 1, 3,18,-3,18, 2, 3,18,-1, 7, 2, 5 },  // 56
        { 0, 2,18,-2, 7, 1, 3, 2, 4, 6,-3, 7 },  // 57
        { 1, 1,18,-2, 2,-3,18,-2,17,-1, 4, 2 },  // 58
        { 0, 3,17,17, 2, 5, 3, 7,18, 6, 4, 2 },  // 59
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 60
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 61
        { 1, 1,18,17, 4, 6, 6, 4, 5, 3, 4, 1 },  // 62
        { 0, 1,18, 5, 3, 6, 2, 3, 8, 1, 3, 7 },  // 63
        { 1, 2,18,17,-2, 2,18, 3, 5, 7,-1, 2 },  // 64
        { 0, 1, 1,18,18, 3, 6,-1, 4, 8, 5, 2 },  // 65
        { 1, 1, 1, 5, 3, 4, 1, 1, 3, 5, 7, 3 },  // 66
        { 0, 1, 3,18,18, 2,18,18,-1, 2, 3,18 },  // 67
        { 1, 2,18,18,-1,18, 2, 3, 4, 6,18, 5 },  // 68
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 69
        { 1, 1,18, 3, 1, 4, 5, 2, 7, 1, 3, 6 },  // 70
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 71
        { 1, 2,18,18,-1,18, 2, 3, 5,-2, 6, 8 },  // 72
        { 1, 1,17,18, 4, 8, 3, 2, 5, 2, 7, 6 },  // 73
        { 1, 4, 1, 2, 5,18,-2, 2, 3, 7,-1, 4 },  // 74
        { 0, 2,18,17,-1, 3, 6,18, 2, 3, 7, 5 },  // 75
        { 0, 1,-2,18, 2,-3, 6,18, 4, 3,-2, 5 },  // 76
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 77
        { 0, 1,17,17, 6, 2, 4, 8, 3, 5,-1,17 },  // 78
        { 1, 1,18, 3,18, 6, 8,18,-2, 5, 7, 2 },  // 79
        { 1, 2,17,17,-3, 2,18,-2, 8, 3, 6,-1 },  // 80
        { 1, 1,18,-2,17,18, 2, 3,-2, 6, 5, 4 },  // 81
        { 1, 2,18,17,-1, 3,18, 2, 5, 3, 6,-3 },  // 82
        { 0, 1,18,17, 2,18, 7,18, 2, 4, 3,17 },  // 83
        { 1, 3,18,18, 5, 6, 4, 3, 4,18, 6, 5 },  // 84
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 85
        { 1, 1, 7, 6, 5, 3, 4, 2, 5, 4, 3, 7 },  // 86
        { 0, 1,-2,18,18,18, 3, 6, 4, 2, 5, 2 },  // 87
        { 0, 3,18,17,-3,18, 3, 2, 5,-1,17, 3 },  // 88
        { 1, 1,17,18, 7, 3, 1, 7, 4, 2, 6, 5 },  // 89
        { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 },  // 90
        { 0, 3,18,18,-1, 3, 2, 7, 5,18, 4, 3 },  // 91
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 92
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 93
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 94
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 95
        { 1, 1,17,18, 2,-2, 4, 8,18, 3, 6, 5 },  // 96
        { 0, 2,18,17, 3, 5,-2, 7, 2,18, 3,-1 },  // 97
        { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 },  // 98
        { 0, 2, 3,17,18,18, 2, 5, 7, 6,18, 3 },  // 99
        { 1, 1,17,18,18, 4, 3, 2,18, 7, 8,-1 },  // 100
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 101
        { 0, 1,17, 1, 2, 3, 5, 6, 1, 4, 8,17 },  // 102
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 103
        { 0, 2,18,17,-1,18,-3, 2, 8, 3, 6,17 },  // 104
        { 1, 1,17,17, 1, 2, 4, 5,-1, 2, 1, 6 },  // 105
        { 1, 1, 1, 2, 6,-2,18, 2,-3, 3,-2, 5 },  // 106
        { 0, 1,18, 3,18, 6,18, 5, 2, 4,-1, 8 },  // 107
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 108
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 109
        { 1, 1,18,18,-1, 2,18, 3, 6, 4,-2, 7 },  // 110
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 111
        { 0, 2,-1,18,18,18, 2,-2, 4, 7, 2, 3 },  // 112
        { 0, 3, 3,17,-2, 5, 2, 7,18, 6, 4, 5 },  // 113
        { 0, 1,17, 6,18, 3, 8, 4, 5, 3, 8,18 },  // 114
        { 0, 2,18, 2, 6, 2,18, 3, 2, 4, 5, 8 },  // 115
        { 0, 1, 3,18,18, 2,18,-1, 2,18, 2,17 },  // 116
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 117
        { 0, 1, 3, 6,17,-2, 5, 1, 2, 7, 4, 8 },  // 118
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 119
        { 1, 3, 3,18,17, 5, 6, 2, 7,-2, 8,18 },  // 120
        { 1, 1,18,-1, 3, 1, 7, 2,-1, 4, 6,17 },  // 121
        { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 },  // 122
        { 0, 2,18, 1, 2,18, 3, 6, 5, 2, 4, 8 },  // 123
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 124
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 125
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 126
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 127
        { 1, 1,17,-2, 2,18,18, 8, 5, 3, 2, 6 },  // 128
        { 0, 1,18,17, 2,18, 3, 2, 7,-2,18, 4 },  // 129
        { 1, 2, 1,18, 2, 3,-1, 5, 6, 4, 7,17 },  // 130
        { 0, 2,18,17, 3, 6,-2, 2, 3, 8, 5,17 },  // 131
        { 0, 2,18,18, 3, 2,18,-1, 2, 4, 3,17 },  // 132
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 133
        { 1, 2,17,-1,18, 2, 3,-2, 5,18, 2, 7 },  // 134
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 135
        { 1, 2,18,-3,18, 2, 3,-2,18, 5, 6,-3 },  // 136
        { 0, 2,18,17, 3, 5,-2, 7, 2,18, 3,-1 },  // 137
        { 1, 1, 1,18,-1, 2, 3, 1,-2, 8, 2, 5 },  // 138
        { 0, 1,18,18, 3, 6,18, 2, 3, 4, 8, 5 },  // 139
        { 0, 1,-2, 1,18, 2,-2, 5, 7,18, 2,-1 },  // 140
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 141
        { 1, 1,17,18,-1, 2, 8, 3, 4, 5, 1, 7 },  // 142
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 143
        { 0, 2,18,18,-1, 2,18, 3,-2, 5, 4, 2 },  // 144
        { 1, 1,18,17, 2,18, 3, 8, 5, 2, 7,17 },  // 145
        { 0, 1,18,18, 3,18, 6, 8,-2, 2, 3, 5 },  // 146
        { 0, 1,18,18, 2,18, 2, 6,18, 2,17, 7 },  // 147
        { 1, 3,18,17,18, 2, 8,18, 5,-1, 3, 6 },  // 148
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 149
        { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 4 },  // 150
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 151
        { 1, 2,18,17,-1, 3, 6,18, 2, 5, 8, 3 },  // 152
        { 0, 1,17,18,18, 4, 7, 2, 3,-2,18, 5 },  // 153
        { 1, 2,18, 1, 2, 6, 2, 5,18, 2, 4, 8 },  // 154
        { 0, 4,18, 4, 1, 2, 3, 5, 4, 1, 2, 6 },  // 155
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 156
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 157
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 158
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 159
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 160
        { 0, 2,18,17, 2,-1,18, 3,-3, 5, 2, 4 },  // 161
        { 0, 1,17,17, 3, 6, 3, 5,-2, 2,18,-1 },  // 162
        { 0, 2,18,18, 3,-2,18, 2,-3, 5, 3, 6 },  // 163
        { 1, 1,17,17, 2, 4, 1, 3, 5, 2, 6,-3 },  // 164
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 165
        { 0, 1,17, 1, 3, 2, 7, 1, 6, 3, 4, 8 },  // 166
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 167
        { 0, 1,17,-1,18, 2, 1, 5, 3, 8,-1,-2 },  // 168
        { 1, 1,17,18,-1, 8, 2, 5, 3, 4, 1, 6 },  // 169
        { 1, 2, 1,18, 3,-1, 5, 1, 2, 4, 7, 6 },  // 170
        { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 },  // 171
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 172
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 173
        { 0, 1, 1,18,-1, 3, 8, 5, 6, 1, 2, 3 },  // 174
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 175
        { 0, 2,18,18, 2, 3, 6,18,-1, 4, 2, 3 },  // 176
        { 1, 1, 1, 3, 5,18, 2, 6, 7, 2, 3, 1 },  // 177
        { 1, 1, 1, 3, 8,18, 5, 2, 7, 1, 3,-2 },  // 178
        { 0, 2,17, 2,18, 3, 6, 2, 4, 5, 8, 3 },  // 179
        { 0, 1,18,17, 2,18, 3, 2, 7,-2,18, 4 },  // 180
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 181
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 182
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 183
        { 1, 2,18,-3,18,-1, 3,-2, 5, 7, 1, 2 },  // 184
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 185
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 186
        { 0, 3,18,18, 2, 6,18, 5,18, 2, 3,17 },  // 187
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 188
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 189
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 190
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 191
        { 1, 3, 1,-1, 1, 3,-2, 2, 5, 7,-3,18 },  // 192
        { 1, 2,18, 7, 3,-3, 2, 8, 2, 5, 4,17 },  // 193
        { 1, 1, 1, 4, 5, 1, 3, 4, 6, 7, 8, 3 },  // 194
        { 0, 1,18,17, 2,18,-1, 2, 3,18, 2, 4 },  // 195
        { 0, 2,18,18,-2,18, 2, 3, 4, 7, 5,17 },  // 196
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 197
        { 1, 1,17,18, 2, 1, 3, 2, 5, 1, 2, 3 },  // 198
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 199
        { 0, 2,18,18,-1, 2, 3, 5, 8, 6, 1,-2 },  // 200
        { 0, 1,17,18, 8, 3, 4, 6, 5, 2, 8, 7 },  // 201
        { 1, 2, 1, 3,-2,18, 2, 5, 1, 7,-1,-2 },  // 202
        { 0, 3,18,17,-1, 3,18, 2, 3, 6, 4,17 },  // 203
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 204
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 205
        { 1, 2,18,18, 4,18, 6, 7, 8, 3,18, 2 },  // 206
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 207
        { 0, 2,17,-3,17, 2,-2, 8, 3,18, 4,-3 },  // 208
        { 1, 1,18,17, 3, 5, 6, 2, 8, 1, 3, 7 },  // 209
        { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 },  // 210
        { 0, 3,18,18, 2, 6,18, 5,18, 2, 3,17 },  // 211
        { 1, 1,18,18, 5, 4, 6, 4, 5, 1, 4, 3 },  // 212
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 213
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 214
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 215
        { 0, 2, 3,17,18,-3, 2, 5,18, 6,-1, 7 },  // 216
        { 1, 1,17,18, 3, 2, 5,-1, 6, 8, 4, 7 },  // 217
        { 1, 1,18, 1,-2, 3, 2, 1, 7, 6, 3, 4 },  // 218
        { 0, 3, 1, 2,17, 3,18, 2, 7, 5, 4,-1 },  // 219
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 220
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 221
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 222
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 223
        { 1, 1,17,-2, 2,18,18, 8, 5, 3, 2, 6 },  // 224
        { 0, 2,18, 5,18, 2, 3, 7,-2, 1, 6, 8 },  // 225
        { 0, 1, 2,-1,18,-1, 2, 4,-3, 5,18, 3 },  // 226
        { 0, 1, 3,17,18, 5, 2,18, 7, 3, 6, 5 },  // 227
        { 1, 4, 1, 2, 5,18,-2, 2, 3, 7,-1, 4 },  // 228
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 229
        { 0, 1, 1,18, 2, 1, 3, 4, 1, 5, 2, 7 },  // 230
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 231
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 232
        { 0, 1,17,17,18, 2, 4, 5,18,-2, 6, 3 },  // 233
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 234
        { 0, 2,18,18,-1, 3, 5, 6, 8,18, 2, 3 },  // 235
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 236
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 237
        { 0, 1,18,18, 4, 6, 8,18, 7, 3, 2, 5 },  // 238
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 239
        { 0, 2,-1,18,18,18, 2, 4,-2, 2, 3, 6 },  // 240
        { 0, 2,18,-2, 7, 1, 3, 2, 4, 6,-3, 7 },  // 241
        { 1, 1,17,18, 8, 3, 4, 6,-2, 5, 3, 8 },  // 242
        { 0, 2,18, 1, 2, 6, 2, 8, 3,18, 5, 4 },  // 243
        { 1, 1, 3,18,18, 2,18, 2,18, 3, 2,18 },  // 244
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 245
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 246
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 247
        { 1, 1, 3,17,18, 5, 2, 6, 7, 1, 4, 8 },  // 248
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 249
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 250
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 251
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 252
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 253
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 254
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 },  // 255
};

static WavpackDecorrSpec very_high_specs [] = {
        { 1, 2,18,18, 2, 3,-2,18, 2, 4, 7, 5, 3, 6, 8,-1,18, 2 },        // 0
        { 0, 1,18,18,-1,18, 2, 3, 4, 6, 5, 7,18,-3, 8, 2,-1, 3 },        // 1
        { 1, 2, 1,18,-2, 4,18, 2, 3, 6,-1, 7, 5,-2,18, 8, 2, 4 },        // 2
        { 0, 1,17,17, 2, 3, 4,18,-1, 5, 6, 7,18, 2, 8,17, 3,-2 },        // 3
        { 1, 1,18,18, 2,18, 3, 2,18, 4,-1, 3,18, 2, 6, 8,17, 5 },        // 4
        { 0, 2,18,17, 2, 3,-2, 5,18,-3, 2, 4, 7, 3, 6, 8, 5,17 },        // 5
        { 1, 1,18,-2, 2,-3,18, 5,-2,18, 2, 3, 6, 2,17, 4, 7,-1 },        // 6
        { 1, 1,17, 8,18, 3,-2, 2, 5, 4,18, 6, 3, 8, 7, 2, 5, 4 },        // 7
        { 0, 2,18,17,-2, 2,18, 3, 2, 5,-3, 4, 7,18, 3, 8, 6, 2 },        // 8
        { 1, 1, 3, 6, 5, 5, 1, 3, 7, 4, 2, 6, 4,18, 3, 7, 5, 6 },        // 9
        { 1, 2, 1,18, 3, 2,-2, 1, 5, 4, 6, 2, 7, 1, 8, 3,-1, 1 },        // 10
        { 0, 1,18,18, 2, 3, 6, 3, 5,-2, 2, 4,18, 3,-2,-1, 6, 7 },        // 11
        { 0, 1,-2,18, 2,18, 7, 2, 6,-2, 3, 4,18,18, 2,-3, 8, 5 },        // 12
        { 0, 2,18,18,18, 2, 4, 3,18, 5, 3, 6,-2, 2, 4,18, 8, 7 },        // 13
        { 0, 1,-2, 1,18, 2,-2,18,-1, 5, 7, 2, 3, 4,18, 2, 6, 2 },        // 14
        { 1, 1,17,18, 3, 2, 1, 7,-1, 2, 4, 3, 5, 6,-2,18, 7, 8 },        // 15
        { 1, 1,18,18, 2,18, 3, 4, 6,-2,18, 5, 8, 2, 3, 7, 4,-1 },        // 16
        { 0, 1,18,18,18,-1, 2, 3, 4, 6, 8,18, 3, 5, 2, 6, 7, 4 },        // 17
        { 1, 1,17,-2,18,18, 2, 5, 3, 8, 2,-1, 6, 1, 3, 4, 7, 5 },        // 18
        { 0, 1,17,17,18, 2, 3, 6,-2, 8, 1, 7, 5, 2, 3, 1, 4, 8 },        // 19
        { 1, 1,17,17, 3, 2, 7, 1, 4, 3, 6, 2, 5,-2, 8, 7,18, 6 },        // 20
        { 0, 1,18,17,-2, 2,18, 3,-3, 7, 6, 5, 2, 4,-1, 8, 3,17 },        // 21
        { 1, 1, 2,18,18,-2, 2, 4,-1, 5,18, 3, 8, 6, 2, 7,17, 4 },        // 22
        { 0, 1,17, 3, 6, 8, 5, 4, 3, 8, 1,18, 7, 2, 4, 5, 6, 3 },        // 23
        { 1, 2,17,18, 4, 8, 3, 2, 5, 7, 6, 8, 2, 7,-2,18, 3, 4 },        // 24
        { 1, 1, 6, 5, 5, 3, 4, 7, 3, 2, 4, 6, 3, 7, 1, 5, 2, 4 },        // 25
        { 1, 1, 1,18,-1, 2, 1, 3, 8,-2, 2, 5, 6, 3, 8, 7,18, 4 },        // 26
        { 0, 1, 1,17,-1,18, 3, 2, 5, 4, 6, 7, 8, 3, 4, 2, 1,-2 },        // 27
        { 0, 1,18, 2,18,18, 2,18, 6,-2,18, 7, 5, 4, 3, 2,18,-2 },        // 28
        { 0, 3, 1, 4,18, 3, 2, 4, 1, 5, 2, 3, 6,18, 8, 7, 2, 4 },        // 29
        { 0, 1,17,-2, 1,-3, 2,18, 3,-2, 4,18, 3, 6, 7,-3, 2, 8 },        // 30
        { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 },        // 31
        { 1, 2,18,-1,17,18, 2, 3,-2,18, 5, 8, 2, 4, 3, 7, 6,-1 },        // 32
        { 1, 1,18,18,18,-2, 4, 2, 3,18, 5, 8, 2, 4, 6, 7,-2, 3 },        // 33
        { 1, 2,18,18,-2,18,-1, 3, 2, 5,18,-2, 7, 2, 3, 4, 6, 8 },        // 34
        { 0, 1,17,18,-1, 2, 4,18, 8, 3, 6, 5, 7,-3, 2, 4, 3,17 },        // 35
        { 1, 1,18,18,17, 2,-1,18, 3, 2,18, 6, 5, 4,18, 7, 2,-1 },        // 36
        { 0, 2, 1,18,-1,18, 3, 2, 4, 6,-3, 7,-1, 5, 1, 2, 3, 8 },        // 37
        { 1, 1, 1,17,-2, 2,-3, 6, 3, 5, 1, 2, 7, 6, 8,-2, 4, 1 },        // 38
        { 0, 1,17,-1, 5, 1, 4, 3, 6, 2,-2,18, 3, 2, 4, 5, 8,-1 },        // 39
        { 0, 2,18,18,17, 2, 3,-2, 5,18, 2, 4, 7, 8, 6,17, 3, 5 },        // 40
        { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 },        // 41
        { 1, 2, 1,-1, 3, 2,18, 7,-2, 5, 2, 6, 4, 3,-1,18, 8, 7 },        // 42
        { 0, 2,18,17, 3,18, 2, 5, 4, 3, 6, 2, 7, 8,18, 3, 4, 5 },        // 43
        { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 },        // 44
        { 0, 2,18,18, 3,-3,18, 2, 6, 5, 3, 7,18, 4,-2, 8, 2, 3 },        // 45
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 46
        { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 },        // 47
        { 1, 1, 3, 6, 5, 5, 1, 3, 7, 4, 2, 6, 4,18, 3, 7, 5, 6 },        // 48
        { 0, 1,18,18,18, 2, 4,-1,18, 8,-1, 2, 3, 4, 6,-2, 1, 7 },        // 49
        { 1, 1,18,-2,17,18, 2, 6, 3,-2, 5, 4, 7, 1,-3, 8, 2, 6 },        // 50
        { 0, 1,17,18,18, 4, 2, 7, 3, 6,-2,18, 8, 4, 5, 2, 7,17 },        // 51
        { 1, 1,18,18, 5, 4, 6, 4, 1, 5, 4, 3, 2, 5, 6, 1, 4, 5 },        // 52
        { 0, 1,18,18,-2,18, 2,-3, 3, 8, 5,18, 6, 4, 3,-1, 7, 2 },        // 53
        { 1, 1,18, 2,-2,-3,18, 5, 2, 3,-2, 4, 6, 1,-3, 2, 7, 8 },        // 54
        { 0, 1,18, 3, 5, 8, 2, 6, 7, 3, 1, 5, 2,-1, 8, 6, 7, 4 },        // 55
        { 1, 1, 4, 3, 8, 1, 5, 6, 2, 5, 8,-2, 2, 7, 3,18, 5, 4 },        // 56
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 57
        { 1, 1,17, 3,18,18, 7, 2, 4,18, 6, 2, 3,-1, 8, 5,18,-3 },        // 58
        { 0, 1, 3,17,18, 2,18, 6, 7,-3,18, 2, 5, 6, 3, 8, 7,-1 },        // 59
        { 1, 1,18,18, 2,18,18, 2,-1, 7, 3,18, 5, 2, 6, 4,-1,18 },        // 60
        { 0, 3,18, 3, 4, 1, 5, 2,18, 4, 2, 3,18, 7, 6, 1, 2, 4 },        // 61
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 62
        { 1, 1,17, 1,18, 2, 3, 6, 4, 5, 7,18, 3, 8, 2, 4,-2,17 },        // 63
        { 1, 2,18,17, 2, 3, 5,18, 6,-2, 7, 3, 2, 4,18, 8,-1, 5 },        // 64
        { 0, 2, 1,18,-1,18, 3, 2, 4, 6,-3, 7,-1, 5, 1, 2, 3, 8 },        // 65
        { 1, 1, 1,18,-1, 8, 2, 6, 3,-2, 1, 2, 5, 4,-3, 8, 6, 3 },        // 66
        { 0, 1,18,18, 2,18, 2,18, 7, 6,18, 2,-2, 3, 5, 4,18, 8 },        // 67
        { 1, 2,18,17, 2, 3,18,-1, 2, 3, 6,18, 5, 4, 3, 7, 2, 8 },        // 68
        { 1, 2,18,18, 3,-2, 4,18, 5, 7, 6, 2, 4,-3, 8, 5,18, 3 },        // 69
        { 1, 1,17,-2,18,18, 2, 5, 3, 8, 2,-1, 6, 1, 3, 4, 7, 5 },        // 70
        { 1, 1, 3,17,18, 5, 7, 2, 4, 6, 1, 8,-1, 3, 7, 4, 1, 2 },        // 71
        { 0, 2, 1,-2, 2,18, 3, 5, 2, 4, 7,-1, 2, 3, 5,18,-2, 4 },        // 72
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 73
        { 1, 1, 1, 2,-2, 6,18,-3, 2, 7, 3,-2, 5, 6, 1, 8, 2, 4 },        // 74
        { 0, 1,18,18,18, 3,-2, 6,18, 2, 4, 3, 5, 8, 7, 6, 2,-2 },        // 75
        { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 },        // 76
        { 0, 1, 3,17,18, 2, 5,18, 6, 7, 5,-2, 2, 4,18, 3, 6, 8 },        // 77
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 78
        { 0, 2,17,-1,18, 2, 4,-1, 8, 3,18, 7,-3, 4, 5, 1, 2,-2 },        // 79
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 8, 6, 4, 5, 7,-1 },        // 80
        { 1, 1,18,18, 3, 6, 4, 8,-2, 2, 5, 3, 7,18, 6, 8, 4, 2 },        // 81
        { 1, 1,17,18,18,-2, 5, 2, 3, 1, 4,-1, 8, 6, 5, 3, 2,18 },        // 82
        { 1, 1,17,17, 1, 2, 4, 5, 2, 6,-1, 3, 1, 1,-2, 4, 2, 7 },        // 83
        { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 },        // 84
        { 0, 1,18,17,-2,-3, 1, 2, 3, 2, 5, 4, 7,-3, 6,-2, 2, 1 },        // 85
        { 1, 1, 1, 3, 5,18, 1, 2, 7, 3, 6, 2, 5, 8,-1, 1, 4, 7 },        // 86
        { 1, 1,17, 3, 6, 8, 1, 4, 5, 3,-2, 7, 2, 8, 5, 6,18, 3 },        // 87
        { 1, 1,17,18, 2, 4, 8,-2, 3, 1, 5, 6, 7, 1, 2, 3, 4, 7 },        // 88
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 89
        { 1, 1, 3, 1, 8,18, 5, 2, 3,18, 6, 7,-2, 4, 3, 2, 8,18 },        // 90
        { 0, 1,18,17, 2,18, 3, 4,-1,18, 7, 6, 2, 8, 4,18,18, 5 },        // 91
        { 0, 1,18,18, 2,18,18, 2, 7,-2, 6, 5, 4, 3,18, 3, 2,17 },        // 92
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 93
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 94
        { 1, 1,17, 8,18, 3, 2, 1, 5, 4, 6,-1, 3,-3, 8,18, 7, 2 },        // 95
        { 1, 2,18,17,18, 2, 3, 5,-2,18, 6,-1, 2, 3, 7, 4, 8,17 },        // 96
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 8, 6, 4, 5, 7,-1 },        // 97
        { 1, 2,18,18,-2,17, 2,18, 3, 4,18, 8, 7,-1, 2, 4, 5,17 },        // 98
        { 0, 2,17,-3,17, 3, 2,-2,18, 8, 4,-3, 2,18, 5, 3,-2, 6 },        // 99
        { 0, 1,18,18, 2,18,18, 2, 7,-2, 6, 5, 4, 3,18, 3, 2,17 },        // 100
        { 0, 2, 1,18,-1, 3, 5, 2,-3,18, 7, 3,-1, 6, 4, 2,17, 5 },        // 101
        { 1, 1,17,-2,17, 2,-3, 1, 5,-1, 4, 6, 3, 2, 8, 7,-2, 5 },        // 102
        { 1, 1, 1,18, 1, 3, 5, 8, 6, 2, 3,-1, 7, 1, 4, 8, 5,-3 },        // 103
        { 0, 2, 3,18,18, 2,18,-2, 6, 5, 7, 2, 4,18, 3, 6,-3, 5 },        // 104
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 105
        { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 },        // 106
        { 0, 4,18, 2,17, 3,18,-2, 2, 6,18, 2, 7, 3, 5, 4, 8,18 },        // 107
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 108
        { 0, 1,18,18, 2, 3, 6, 3, 5,-2, 2, 4,18, 3,-2,-1, 6, 7 },        // 109
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 110
        { 1, 1,17, 1, 2, 5, 3,-2, 1, 4, 3, 7, 6,-3, 2, 1, 1, 2 },        // 111
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 112
        { 1, 1,18,18,-2,18,-2, 2, 3, 6,18, 4,-1, 2, 3, 8, 1, 4 },        // 113
        { 1, 1,17,-2,17, 2,-3, 1, 5,-1, 4, 6, 3, 2, 8, 7,-2, 5 },        // 114
        { 0, 1,17,17,18, 3, 2,18,18, 6, 8, 2,-2, 3, 5, 4,17,18 },        // 115
        { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 },        // 116
        { 1, 1, 1, 3,-3,18,18, 6, 5,18, 2,-1, 3, 8, 7,-3, 4,17 },        // 117
        { 1, 1,18, 1, 2, 1, 3, 8, 7, 4, 1, 5, 2,-1,-3,18, 6, 2 },        // 118
        { 0, 1,18, 3, 5, 2, 6, 8,18, 5, 7, 2, 3,-1, 6, 7, 8, 5 },        // 119
        { 0, 2,18, 3,-2, 7, 8, 2, 5, 4,-3, 8, 3, 2,18, 5, 4, 6 },        // 120
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 121
        { 1, 3, 1, 1, 2, 5, 2, 7, 4, 3,-1,18,-2, 8, 2, 1, 6, 7 },        // 122
        { 0, 1, 3,17,18, 5, 2, 6, 7,18, 4, 5, 3, 6,18, 2, 7, 8 },        // 123
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 124
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 125
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 126
        { 0, 1, 1,18, 1, 2, 3, 5, 1, 2, 6, 7, 4, 3, 8, 1,17, 5 },        // 127
        { 1, 2,17,-1,18,-2, 2, 3, 5,18, 2, 4, 6, 7, 3,-1, 5, 8 },        // 128
        { 1, 1,18,18,-3,18,-2, 2, 3,-2,18, 6, 4, 5, 8, 3,17,-3 },        // 129
        { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 7, 3, 4,-3, 6,18, 8 },        // 130
        { 0, 2,18,18, 2, 3, 5,18, 2, 4, 3, 6,18, 7, 8,-1, 5, 2 },        // 131
        { 0, 1,18,17,-1, 2,18, 3, 2,18, 4, 3,18, 2, 6, 5, 8,17 },        // 132
        { 0, 2,18,17, 2, 3,18, 5,-1, 6, 7, 8, 2, 3, 4, 5,18, 6 },        // 133
        { 1, 2,18,-3,18, 2, 3,-2,-3, 5,18, 7, 6, 2, 4, 3, 8,-2 },        // 134
        { 1, 1,17,18,18,-2, 2, 3, 5, 4, 8,18,-1, 5, 3, 6,-2, 7 },        // 135
        { 1, 2,18,17, 2,-2,18, 3,-1, 4,18, 2, 7, 5, 3, 8, 6, 4 },        // 136
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 137
        { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 },        // 138
        { 0, 2,18,18, 3, 3,-2, 2, 5,18, 6, 3,-1, 4, 7,-1, 1, 2 },        // 139
        { 0, 1,-2, 1,18, 2,-2, 5, 7,18, 3, 2, 6, 2,-1, 4,-2,17 },        // 140
        { 0, 2,18,18,18, 2, 3,-2,18, 5, 4, 2, 6, 8, 3,-2, 4,18 },        // 141
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 142
        { 1, 1,17,18,-1, 3, 2, 5, 1, 3, 2, 8, 4, 7, 6, 2,-1, 5 },        // 143
        { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 },        // 144
        { 0, 1,18,18,-2,18, 2, 3, 4, 5, 6,18, 8, 2, 3, 7,-2, 4 },        // 145
        { 0, 1,18,-2,18,18,-3,-2, 2, 3, 5, 8, 1, 2, 6, 4, 7,-1 },        // 146
        { 0, 1,18,17, 2,18, 3,-2, 2, 7, 6, 4,18, 3, 8, 7, 4, 2 },        // 147
        { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 },        // 148
        { 1, 1,18,17,18, 2, 5, 3,-2,18, 6, 2, 3, 4, 8, 7, 5,-1 },        // 149
        { 0, 1, 2,-1,18,-1, 2, 4,-3,18, 5, 3, 6,18, 2, 4, 7, 8 },        // 150
        { 1, 1,17,18, 8, 3, 6, 4,-1, 5, 2, 7, 3, 8, 6, 5,18, 4 },        // 151
        { 0, 2,18, 3,-2, 7, 8, 2, 5, 4,-3, 8, 3, 2,18, 5, 4, 6 },        // 152
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 153
        { 1, 1, 1,18,-1, 8, 2, 6, 3,-2, 1, 2, 5, 4,-3, 8, 6, 3 },        // 154
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 155
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 156
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 157
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 158
        { 0, 1,17,18,18, 4, 2, 7, 3, 6,-2,18, 8, 4, 5, 2, 7,17 },        // 159
        { 1, 2,18,-1,18, 3,-2,18, 2, 5, 3, 6, 7, 2,-1,18, 8, 4 },        // 160
        { 1, 2, 1,18,-2, 4,18, 2, 3, 6,-1, 7, 5,-2,18, 8, 2, 4 },        // 161
        { 1, 2, 1,18,-3, 2, 3,18,-1, 5, 6, 2, 8, 3, 4, 1,-2, 7 },        // 162
        { 0, 1, 1,17,-1,18, 3, 2, 5, 4, 6, 7, 8, 3, 4, 2, 1,-2 },        // 163
        { 1, 1,18,17,18, 4, 3, 5, 1, 2, 6, 3, 4, 7, 1, 8, 5, 2 },        // 164
        { 0, 1,18,-2, 7, 1, 3, 2,-3, 4, 6,-2, 7, 8, 1, 5, 4, 3 },        // 165
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 166
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 167
        { 0, 2,18,18,18,-2, 2, 5, 3, 7,18, 2, 4,-3, 5, 6, 3, 8 },        // 168
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 169
        { 0, 3, 3,18,-1, 5, 2, 7,18, 6, 5, 2, 4, 3,-1, 7,18, 6 },        // 170
        { 0, 2,18,18,18, 4, 3, 2, 6, 4, 8,18, 5, 3, 2, 7,-2, 6 },        // 171
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 172
        { 0, 2,18,18,18, 2, 3,-2,18, 5, 4, 2, 6, 8, 3,-2, 4,18 },        // 173
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 174
        { 1, 1,17, 8,18, 3, 2, 1, 5, 4, 6,-1, 3,-3, 8,18, 7, 2 },        // 175
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 176
        { 0, 1,-1,18,18,18, 2, 4, 6,-2, 2, 8, 3, 4,18, 7,-1, 6 },        // 177
        { 0, 1,18, 1,-2, 2, 4, 1, 3,-1, 2, 5, 7, 1, 6, 8,-2,17 },        // 178
        { 0, 1,17,17,18, 2, 5, 4,18, 3, 8, 7, 4, 6, 8, 1, 5, 2 },        // 179
        { 1, 2,18,18, 5, 4, 6, 3, 4,18, 8, 4,-1, 7, 5, 3, 6, 2 },        // 180
        { 0, 1,18,18,-3,18, 3, 6, 2, 5, 7,18, 3, 8,-1, 4, 5, 2 },        // 181
        { 1, 1,18, 2,-2,-3,18, 5, 2,-2, 4, 3, 6,18, 8,-1, 2, 7 },        // 182
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 183
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 184
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 185
        { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 },        // 186
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 187
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 188
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 189
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 190
        { 0, 1,17,18, 3,18, 2, 5, 4, 7,-3, 6, 3, 2,18, 4, 7, 3 },        // 191
        { 1, 1, 1, 7, 4, 5, 3, 4, 5, 1, 3, 6, 3, 2, 4, 8,-2, 7 },        // 192
        { 0, 1, 1,18,-1,-2,18, 3, 2,-1, 6, 7, 4, 5, 3,18, 2,-3 },        // 193
        { 1, 1,18,18,-1, 3, 6,18, 5, 4, 8, 2, 3, 6,18, 7, 4,-2 },        // 194
        { 0, 2,18,18, 2, 6,18, 2,18, 5, 3,18, 2, 4, 7, 8, 3,18 },        // 195
        { 1, 1, 3,18,18, 5,18, 6, 2, 4, 7,-2,18, 5, 8, 6, 3, 2 },        // 196
        { 0, 1,18,-2, 7, 1, 3, 2,-3, 4, 6,-2, 7, 8, 1, 5, 4, 3 },        // 197
        { 1, 1,18,-2,18, 2, 5,18, 3,-2, 4, 7, 2,-1, 8, 6, 5, 1 },        // 198
        { 1, 1,17,17, 5,18, 4, 1, 2, 8, 6, 4,-2, 3, 5,-1, 1, 8 },        // 199
        { 0, 2, 1, 2,17, 3, 7,18, 2,-1, 4, 5,18, 2, 7, 3, 6, 8 },        // 200
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 201
        { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 },        // 202
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 203
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 204
        { 0, 2,18,18,18, 2,-2, 3, 6, 4, 8,18, 2, 5, 7, 4, 3, 6 },        // 205
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 206
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 207
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 208
        { 1, 1,18, 1, 8, 3, 5, 6, 4,-1, 8, 3, 7,18, 2, 5, 8, 4 },        // 209
        { 1, 1,17,18, 5, 2, 4, 3, 1, 6,-2, 1, 3, 2, 4, 5,-1,17 },        // 210
        { 1, 1,18,17, 2,18, 3,-3, 7, 2, 6, 4, 3, 5,18, 8, 2,-2 },        // 211
        { 1, 1,18,17,18, 4, 3, 5,-1,18, 2, 7, 8, 4, 6, 3,18, 5 },        // 212
        { 0, 1,18,17,18,-2, 2,-3, 3, 4, 8, 5, 2,18, 6, 3, 7,-2 },        // 213
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 214
        { 1, 1,17,18, 8, 3, 4, 6,18, 5,-2, 3, 8, 5, 2, 4, 7, 6 },        // 215
        { 0, 1,18,-2, 3, 5, 1, 7, 3, 2, 6,-3, 4, 1, 5, 8, 3,-2 },        // 216
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 217
        { 1, 1, 3,17,18, 5,-1,18, 2, 6, 7,18, 5, 3,-3,-1, 6, 2 },        // 218
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 219
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 220
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 221
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 222
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 223
        { 1, 3,18,17,-2, 3,-1,18, 2, 5, 3, 7, 6, 2, 4, 8,18, 5 },        // 224
        { 0, 1,18,-1,18, 2,18, 3, 5,18, 2, 8,18, 5, 4,-1, 6, 2 },        // 225
        { 1, 2,18,-2,18,18, 2, 3, 4,-3, 2, 5,18, 7, 4, 3, 8, 6 },        // 226
        { 0, 2,17,-1,18, 2,-1, 1, 7, 3, 8, 5,-2, 4, 1, 2,-3, 6 },        // 227
        { 0, 1,18,17, 2,18, 2,18, 6, 7, 4, 3,18, 5, 2,-2,17, 8 },        // 228
        { 0, 3,18,17, 2, 3,-3,-1,18, 2, 4, 5,18, 7, 3, 2,-3, 6 },        // 229
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 230
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 231
        { 0, 2, 3,18,18,18, 2, 6, 5,18, 7, 2, 4, 6,18, 5, 3, 8 },        // 232
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 233
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 234
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 235
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 236
        { 0, 1,18,18, 3, 6, 3,-2, 2,18, 5,-1, 7, 3, 4,-2, 2, 6 },        // 237
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 238
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 239
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 240
        { 1, 1,18,17,18,18,-2, 2, 3,-3,18, 6, 4, 2,-2, 8, 3, 7 },        // 241
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 242
        { 0, 1,18,18,18, 4, 2, 7, 8,18, 3, 2,-2, 4, 7, 6,17, 5 },        // 243
        { 1, 1,18,18,-1,-2, 8, 3,18, 6, 3, 5, 8, 2, 4, 7, 1, 6 },        // 244
        { 1, 1, 1,-3, 3,18,18, 2,-1, 3, 6, 5,18, 4, 7,-2, 8, 3 },        // 245
        { 1, 1, 1,18, 4, 2, 5,18, 1, 3,-1, 6, 1, 4, 8, 2, 5, 1 },        // 246
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 247
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 248
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 249
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 250
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 251
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 252
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 253
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 254
        { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 },        // 255
};

#define NUM_FAST_SPECS (sizeof (fast_specs) / sizeof (fast_specs [0]))
#define NUM_DEFAULT_SPECS (sizeof (default_specs) / sizeof (default_specs [0]))
#define NUM_HIGH_SPECS (sizeof (high_specs) / sizeof (high_specs [0]))
#define NUM_VERY_HIGH_SPECS (sizeof (very_high_specs) / sizeof (very_high_specs [0]))

///////////////////////////// executable code ////////////////////////////////

// This function initializes everything required to pack WavPack bitstreams
// and must be called BEFORE any other function in this module.

void pack_init (WavpackContext *wpc)
{
    WavpackStream *wps = wpc->streams [wpc->current_stream];

    wps->sample_index = 0;
    wps->delta_decay = 2.0;
    CLEAR (wps->decorr_passes);
    CLEAR (wps->dc);

    if (wpc->config.flags & CONFIG_AUTO_SHAPING)
        wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] =
            (wpc->config.sample_rate < 64000 || (wps->wphdr.flags & CROSS_DECORR)) ? -512L << 16 : 1024L << 16;
    else {
        int32_t weight = (int32_t) floor (wpc->config.shaping_weight * 1024.0 + 0.5);

        if (weight <= -1000)
            weight = -1000;

        wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = weight << 16;
    }

    if (!wpc->config.xmode)
        wps->num_passes = 0;
    else if (wpc->config.xmode == 1)
        wps->num_passes = 2;
    else if (wpc->config.xmode == 2)
        wps->num_passes = 4;
    else
        wps->num_passes = 9;

    if (wpc->config.flags & CONFIG_VERY_HIGH_FLAG) {
        wps->num_decorrs = NUM_VERY_HIGH_SPECS;
        wps->decorr_specs = very_high_specs;
    }
    else if (wpc->config.flags & CONFIG_HIGH_FLAG) {
        wps->num_decorrs = NUM_HIGH_SPECS;
        wps->decorr_specs = high_specs;
    }
    else if (wpc->config.flags & CONFIG_FAST_FLAG) {
        wps->num_decorrs = NUM_FAST_SPECS;
        wps->decorr_specs = fast_specs;
    }
    else {
        wps->num_decorrs = NUM_DEFAULT_SPECS;
        wps->decorr_specs = default_specs;
    }

    init_words (wps);
}

// Allocate room for and copy the decorrelation terms from the decorr_passes
// array into the specified metadata structure. Both the actual term id and
// the delta are packed into single characters.

void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd)
{
    int tcount = wps->num_terms;
    struct decorr_pass *dpp;
    char *byteptr;

    byteptr = wpmd->data = malloc (tcount + 1);
    wpmd->id = ID_DECORR_TERMS;

    for (dpp = wps->decorr_passes; tcount--; ++dpp)
        *byteptr++ = ((dpp->term + 5) & 0x1f) | ((dpp->delta << 5) & 0xe0);

    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the decorrelation term weights from the
// decorr_passes array into the specified metadata structure. The weights
// range +/-1024, but are rounded and truncated to fit in signed chars for
// metadata storage. Weights are separate for the two channels

void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd)
{
    struct decorr_pass *dpp = wps->decorr_passes;
    int tcount = wps->num_terms, i;
    char *byteptr;

    byteptr = wpmd->data = malloc ((tcount * 2) + 1);
    wpmd->id = ID_DECORR_WEIGHTS;

    for (i = wps->num_terms - 1; i >= 0; --i)
        if (store_weight (dpp [i].weight_A) ||
            (!(wps->wphdr.flags & MONO_DATA) && store_weight (dpp [i].weight_B)))
                break;

    tcount = i + 1;

    for (i = 0; i < wps->num_terms; ++i) {
        if (i < tcount) {
            dpp [i].weight_A = restore_weight (*byteptr++ = store_weight (dpp [i].weight_A));

            if (!(wps->wphdr.flags & MONO_DATA))
                dpp [i].weight_B = restore_weight (*byteptr++ = store_weight (dpp [i].weight_B));
        }
        else
            dpp [i].weight_A = dpp [i].weight_B = 0;
    }

    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the decorrelation samples from the decorr_passes
// array into the specified metadata structure. The samples are signed 32-bit
// values, but are converted to signed log2 values for storage in metadata.
// Values are stored for both channels and are specified from the first term
// with unspecified samples set to zero. The number of samples stored varies
// with the actual term value, so those must obviously be specified before
// these in the metadata list. Any number of terms can have their samples
// specified from no terms to all the terms, however I have found that
// sending more than the first term's samples is a waste. The "wcount"
// variable can be set to the number of terms to have their samples stored.

void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd)
{
    int tcount = wps->num_terms, wcount = 1, temp;
    struct decorr_pass *dpp;
    uchar *byteptr;

    byteptr = wpmd->data = malloc (256);
    wpmd->id = ID_DECORR_SAMPLES;

    for (dpp = wps->decorr_passes; tcount--; ++dpp)
        if (wcount) {
            if (dpp->term > MAX_TERM) {
                dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
                *byteptr++ = temp;
                *byteptr++ = temp >> 8;
                dpp->samples_A [1] = exp2s (temp = log2s (dpp->samples_A [1]));
                *byteptr++ = temp;
                *byteptr++ = temp >> 8;

                if (!(wps->wphdr.flags & MONO_DATA)) {
                    dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
                    *byteptr++ = temp;
                    *byteptr++ = temp >> 8;
                    dpp->samples_B [1] = exp2s (temp = log2s (dpp->samples_B [1]));
                    *byteptr++ = temp;
                    *byteptr++ = temp >> 8;
                }
            }
            else if (dpp->term < 0) {
                dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0]));
                *byteptr++ = temp;
                *byteptr++ = temp >> 8;
                dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0]));
                *byteptr++ = temp;
                *byteptr++ = temp >> 8;
            }
            else {
                int m = 0, cnt = dpp->term;

                while (cnt--) {
                    dpp->samples_A [m] = exp2s (temp = log2s (dpp->samples_A [m]));
                    *byteptr++ = temp;
                    *byteptr++ = temp >> 8;

                    if (!(wps->wphdr.flags & MONO_DATA)) {
                        dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m]));
                        *byteptr++ = temp;
                        *byteptr++ = temp >> 8;
                    }

                    m++;
                }
            }

            wcount--;
        }
        else {
            CLEAR (dpp->samples_A);
            CLEAR (dpp->samples_B);
        }

    wpmd->byte_length = (int32_t)(byteptr - (uchar *) wpmd->data);
}

// Allocate room for and copy the noise shaping info into the specified
// metadata structure. These would normally be written to the
// "correction" file and are used for lossless reconstruction of
// hybrid data. The "delta" parameter is not yet used in encoding as it
// will be part of the "quality" mode.

void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
    char *byteptr;
    int temp;

    byteptr = wpmd->data = malloc (12);
    wpmd->id = ID_SHAPING_WEIGHTS;

    wps->dc.error [0] = exp2s (temp = log2s (wps->dc.error [0]));
    *byteptr++ = temp;
    *byteptr++ = temp >> 8;
    wps->dc.shaping_acc [0] = exp2s (temp = log2s (wps->dc.shaping_acc [0]));
    *byteptr++ = temp;
    *byteptr++ = temp >> 8;

    if (!(wps->wphdr.flags & MONO_DATA)) {
        wps->dc.error [1] = exp2s (temp = log2s (wps->dc.error [1]));
        *byteptr++ = temp;
        *byteptr++ = temp >> 8;
        wps->dc.shaping_acc [1] = exp2s (temp = log2s (wps->dc.shaping_acc [1]));
        *byteptr++ = temp;
        *byteptr++ = temp >> 8;
    }

    if (wps->dc.shaping_delta [0] | wps->dc.shaping_delta [1]) {
        wps->dc.shaping_delta [0] = exp2s (temp = log2s (wps->dc.shaping_delta [0]));
        *byteptr++ = temp;
        *byteptr++ = temp >> 8;

        if (!(wps->wphdr.flags & MONO_DATA)) {
            wps->dc.shaping_delta [1] = exp2s (temp = log2s (wps->dc.shaping_delta [1]));
            *byteptr++ = temp;
            *byteptr++ = temp >> 8;
        }
    }

    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the int32 data values into the specified
// metadata structure. This data is used for integer data that has more
// than 24 bits of magnitude or, in some cases, it's used to eliminate
// redundant bits from any audio stream.

void write_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
    char *byteptr;

    byteptr = wpmd->data = malloc (4);
    wpmd->id = ID_INT32_INFO;
    *byteptr++ = wps->int32_sent_bits;
    *byteptr++ = wps->int32_zeros;
    *byteptr++ = wps->int32_ones;
    *byteptr++ = wps->int32_dups;
    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the multichannel information into the specified
// metadata structure. The first byte is the total number of channels and the
// following bytes represent the channel_mask as described for Microsoft
// WAVEFORMATEX.

void write_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
    uint32_t mask = wpc->config.channel_mask;
    char *byteptr;

    byteptr = wpmd->data = malloc (4);
    wpmd->id = ID_CHANNEL_INFO;
    *byteptr++ = wpc->config.num_channels;

    while (mask) {
        *byteptr++ = mask;
        mask >>= 8;
    }

    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the configuration information into the specified
// metadata structure. Currently, we just store the upper 3 bytes of
// config.flags and only in the first block of audio data. Note that this is
// for informational purposes not required for playback or decoding (like
// whether high or fast mode was specified).

void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
{
    char *byteptr;

    byteptr = wpmd->data = malloc (4);
    wpmd->id = ID_CONFIG_BLOCK;
    *byteptr++ = (char) (wpc->config.flags >> 8);
    *byteptr++ = (char) (wpc->config.flags >> 16);
    *byteptr++ = (char) (wpc->config.flags >> 24);
    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Allocate room for and copy the non-standard sampling rateinto the specified
// metadata structure. We just store the lower 3 bytes of the sampling rate.
// Note that this would only be used when the sampling rate was not included
// in the table of 15 "standard" values.

void write_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)

{
    char *byteptr;

    byteptr = wpmd->data = malloc (4);
    wpmd->id = ID_SAMPLE_RATE;
    *byteptr++ = (char) (wpc->config.sample_rate);
    *byteptr++ = (char) (wpc->config.sample_rate >> 8);
    *byteptr++ = (char) (wpc->config.sample_rate >> 16);
    wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data);
}

// Pack an entire block of samples (either mono or stereo) into a completed
// WavPack block. This function is actually a shell for pack_samples() and
// performs tasks like handling any shift required by the format, preprocessing
// of floating point data or integer data over 24 bits wide, and implementing
// the "extra" mode (via the extra?.c modules). It is assumed that there is
// sufficient space for the completed block at "wps->blockbuff" and that
// "wps->blockend" points to the end of the available space. A return value of
// FALSE indicates an error.

static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values);
static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values);
static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values);
static int pack_samples (WavpackContext *wpc, int32_t *buffer);

int pack_block (WavpackContext *wpc, int32_t *buffer)
{
    WavpackStream *wps = wpc->streams [wpc->current_stream];
    uint32_t flags = wps->wphdr.flags, sflags = wps->wphdr.flags;
    int32_t sample_count = wps->wphdr.block_samples, *orig_data = NULL;

    if (!(flags & MONO_FLAG) && wpc->stream_version >= 0x410) {
        int32_t lor = 0, diff = 0;
        int32_t *sptr, *dptr, i;

        for (sptr = buffer, i = 0; i < (int32_t) sample_count; sptr += 2, i++) {
            lor |= sptr [0] | sptr [1];
            diff |= sptr [0] - sptr [1];

            if (lor && diff)
                break;
        }

        if (i == sample_count && lor && !diff) {
            flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
            wps->wphdr.flags = flags |= FALSE_STEREO;
            dptr = buffer;
            sptr = buffer;

            for (i = sample_count; i--; sptr++)
                *dptr++ = *sptr++;

            if (!wps->false_stereo) {
                wps->false_stereo = 1;
                wps->num_terms = 0;
                init_words (wps);
            }
        }
        else if (wps->false_stereo) {
            wps->false_stereo = 0;
            wps->num_terms = 0;
            init_words (wps);
        }
    }

    if (flags & SHIFT_MASK) {
        int shift = (flags & SHIFT_MASK) >> SHIFT_LSB;
        int mag = (flags & MAG_MASK) >> MAG_LSB;
        uint32_t cnt = sample_count;
        int32_t *ptr = buffer;

        if (flags & MONO_DATA)
            while (cnt--)
                *ptr++ >>= shift;
        else
            while (cnt--) {
                *ptr++ >>= shift;
                *ptr++ >>= shift;
            }

        if ((mag -= shift) < 0)
            flags &= ~MAG_MASK;
        else
            flags -= (1 << MAG_LSB) * shift;

        wps->wphdr.flags = flags;
    }

    if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) {
        if ((!(flags & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) {
            orig_data = malloc (sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));
            memcpy (orig_data, buffer, sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2));

            if (flags & FLOAT_DATA) {
                wps->float_norm_exp = wpc->config.float_norm_exp;

                if (!scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
                    free (orig_data);
                    orig_data = NULL;
                }
            }
            else {
                if (!scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) {
                    free (orig_data);
                    orig_data = NULL;
                }
            }
        }
        else {
            if (flags & FLOAT_DATA) {
                wps->float_norm_exp = wpc->config.float_norm_exp;

                if (scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2))
                    wpc->lossy_blocks = TRUE;
            }
            else if (scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2))
                wpc->lossy_blocks = TRUE;
        }

        wps->num_terms = 0;
    }
    else {
        scan_int32_quick (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2);

        if (wps->shift != wps->int32_zeros + wps->int32_ones + wps->int32_dups) {
            wps->shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups;
            wps->num_terms = 0;
        }
    }

    if (!wps->num_passes && !wps->num_terms) {
        wps->num_passes = 1;

        if (flags & MONO_DATA)
            execute_mono (wpc, buffer, 1, 0);
        else
            execute_stereo (wpc, buffer, 1, 0);

        wps->num_passes = 0;
    }

    if (!pack_samples (wpc, buffer)) {
        wps->wphdr.flags = sflags;

        if (orig_data)
            free (orig_data);

        return FALSE;
    }
    else
        wps->wphdr.flags = sflags;

    if (orig_data) {
        uint32_t data_count;
        uchar *cptr;

        if (wpc->wvc_flag)
            cptr = wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 8;
        else
            cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8;

        bs_open_write (&wps->wvxbits, cptr + 8, wpc->wvc_flag ? wps->block2end : wps->blockend);

        if (flags & FLOAT_DATA)
            send_float_data (wps, (f32*) orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2);
        else
            send_int32_data (wps, orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2);

        data_count = bs_close_write (&wps->wvxbits);
        free (orig_data);

        if (data_count) {
            if (data_count != (uint32_t) -1) {
                *cptr++ = ID_WVX_BITSTREAM | ID_LARGE;
                *cptr++ = (data_count += 4) >> 1;
                *cptr++ = data_count >> 9;
                *cptr++ = data_count >> 17;
                *cptr++ = wps->crc_x;
                *cptr++ = wps->crc_x >> 8;
                *cptr++ = wps->crc_x >> 16;
                *cptr = wps->crc_x >> 24;

                if (wpc->wvc_flag)
                    ((WavpackHeader *) wps->block2buff)->ckSize += data_count + 4;
                else
                    ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4;
            }
            else
                return FALSE;
        }
    }

    return TRUE;
}

// Quickly scan a buffer of long integer data and determine whether any
// redundancy in the LSBs can be used to reduce the data's magnitude. If yes,
// then the INT32_DATA flag is set and the int32 parameters are set. This
// version is designed to terminate as soon as it figures out that no
// redundancy is available so that it can be used for all files.

static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values)
{
    uint32_t magdata = 0, ordata = 0, xordata = 0, anddata = ~0;
    int total_shift = 0;
    int32_t *dp, count;

    wps->int32_sent_bits = wps->int32_zeros = wps->int32_ones = wps->int32_dups = 0;

    for (dp = values, count = num_values; count--; dp++) {
        magdata |= (*dp < 0) ? ~*dp : *dp;
        xordata |= *dp ^ -(*dp & 1);
        anddata &= *dp;
        ordata |= *dp;

        if ((ordata & 1) && !(anddata & 1) && (xordata & 2))
            return;
    }

    wps->wphdr.flags &= ~MAG_MASK;

    while (magdata) {
        wps->wphdr.flags += 1 << MAG_LSB;
        magdata >>= 1;
    }

    if (!(wps->wphdr.flags & MAG_MASK))
        return;

    if (!(ordata & 1))
        while (!(ordata & 1)) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_zeros++;
            total_shift++;
            ordata >>= 1;
        }
    else if (anddata & 1)
        while (anddata & 1) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_ones++;
            total_shift++;
            anddata >>= 1;
        }
    else if (!(xordata & 2))
        while (!(xordata & 2)) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_dups++;
            total_shift++;
            xordata >>= 1;
        }

    if (total_shift) {
        wps->wphdr.flags |= INT32_DATA;

        for (dp = values, count = num_values; count--; dp++)
            *dp >>= total_shift;
    }
}

// Scan a buffer of long integer data and determine whether any redundancy in
// the LSBs can be used to reduce the data's magnitude. If yes, then the
// INT32_DATA flag is set and the int32 parameters are set. If bits must still
// be transmitted literally to get down to 24 bits (which is all the integer
// compression code can handle) then we return TRUE to indicate that a wvx
// stream must be created in either lossless mode.

static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values)
{
    uint32_t magdata = 0, ordata = 0, xordata = 0, anddata = ~0;
    uint32_t crc = 0xffffffff;
    int total_shift = 0;
    int32_t *dp, count;

    wps->int32_sent_bits = wps->int32_zeros = wps->int32_ones = wps->int32_dups = 0;

    for (dp = values, count = num_values; count--; dp++) {
        crc = crc * 9 + (*dp & 0xffff) * 3 + ((*dp >> 16) & 0xffff);
        magdata |= (*dp < 0) ? ~*dp : *dp;
        xordata |= *dp ^ -(*dp & 1);
        anddata &= *dp;
        ordata |= *dp;
    }

    wps->crc_x = crc;
    wps->wphdr.flags &= ~MAG_MASK;

    while (magdata) {
        wps->wphdr.flags += 1 << MAG_LSB;
        magdata >>= 1;
    }

    if (!((wps->wphdr.flags & MAG_MASK) >> MAG_LSB)) {
        wps->wphdr.flags &= ~INT32_DATA;
        return FALSE;
    }

    if (!(ordata & 1))
        while (!(ordata & 1)) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_zeros++;
            total_shift++;
            ordata >>= 1;
        }
    else if (anddata & 1)
        while (anddata & 1) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_ones++;
            total_shift++;
            anddata >>= 1;
        }
    else if (!(xordata & 2))
        while (!(xordata & 2)) {
            wps->wphdr.flags -= 1 << MAG_LSB;
            wps->int32_dups++;
            total_shift++;
            xordata >>= 1;
        }

    if (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) > 23) {
        wps->int32_sent_bits = (uchar)(((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) - 23);
        total_shift += wps->int32_sent_bits;
        wps->wphdr.flags &= ~MAG_MASK;
        wps->wphdr.flags += 23 << MAG_LSB;
    }

    if (total_shift) {
        wps->wphdr.flags |= INT32_DATA;

        for (dp = values, count = num_values; count--; dp++)
            *dp >>= total_shift;
    }

    return wps->int32_sent_bits;
}

// For the specified buffer values and the int32 parameters stored in "wps",
// send the literal bits required to the "wvxbits" bitstream.

static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values)
{
    int sent_bits = wps->int32_sent_bits, pre_shift;
    int32_t mask = (1 << sent_bits) - 1;
    int32_t count, value, *dp;

    pre_shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups;

    if (sent_bits)
        for (dp = values, count = num_values; count--; dp++) {
            value = (*dp >> pre_shift) & mask;
            putbits (value, sent_bits, &wps->wvxbits);
        }
}

// Pack an entire block of samples (either mono or stereo) into a completed
// WavPack block. It is assumed that there is sufficient space for the
// completed block at "wps->blockbuff" and that "wps->blockend" points to the
// end of the available space. A return value of FALSE indicates an error.
// Any unsent metadata is transmitted first, then required metadata for this
// block is sent, and finally the compressed integer data is sent. If a "wpx"
// stream is required for floating point data or large integer data, then this
// must be handled outside this function. To find out how much data was written
// the caller must look at the ckSize field of the written WavpackHeader, NOT
// the one in the WavpackStream.

static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);
static void decorr_stereo_pass_id2 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count);

static int pack_samples (WavpackContext *wpc, int32_t *buffer)
{
    WavpackStream *wps = wpc->streams [wpc->current_stream];
    uint32_t flags = wps->wphdr.flags, data_count, crc, crc2, i;
    uint32_t sample_count = wps->wphdr.block_samples;
    int tcount, lossy = FALSE, m = 0;
    double noise_acc = 0.0, noise;
    struct decorr_pass *dpp;
    WavpackMetadata wpmd;
    int32_t *bptr;

    crc = crc2 = 0xffffffff;

    if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA)) {
        int32_t *eptr = buffer + sample_count;

        for (bptr = buffer; bptr < eptr;)
            crc += (crc << 1) + *bptr++;

        if (wps->num_passes)
            execute_mono (wpc, buffer, !wps->num_terms, 1);
    }
    else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) {
        int32_t *eptr = buffer + (sample_count * 2);

        for (bptr = buffer; bptr < eptr; bptr += 2)
            crc += (crc << 3) + (bptr [0] << 1) + bptr [0] + bptr [1];

        if (wps->num_passes) {
            execute_stereo (wpc, buffer, !wps->num_terms, 1);
            flags = wps->wphdr.flags;
        }
    }
    else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA)) {
        if (wps->num_passes)
            execute_mono (wpc, buffer, !wps->num_terms, 0);
    }
    else if ((flags & HYBRID_FLAG) && !(flags & MONO_DATA)) {
        if (wps->num_passes) {
            execute_stereo (wpc, buffer, !wps->num_terms, 0);
            flags = wps->wphdr.flags;
        }
    }

    wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
    memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader));

    if (wpc->metacount) {
        WavpackMetadata *wpmdp = wpc->metadata;

        while (wpc->metacount) {
            copy_metadata (wpmdp, wps->blockbuff, wps->blockend);
            wpc->metabytes -= wpmdp->byte_length;
            free_metadata (wpmdp++);
            wpc->metacount--;
        }

        free (wpc->metadata);
        wpc->metadata = NULL;
    }

    if (!sample_count)
        return TRUE;

    write_decorr_terms (wps, &wpmd);
    copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
    free_metadata (&wpmd);

    write_decorr_weights (wps, &wpmd);
    copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
    free_metadata (&wpmd);

    write_decorr_samples (wps, &wpmd);
    copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
    free_metadata (&wpmd);

    write_entropy_vars (wps, &wpmd);
    copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
    free_metadata (&wpmd);

    if ((flags & SRATE_MASK) == SRATE_MASK && wpc->config.sample_rate != 44100) {
        write_sample_rate (wpc, &wpmd);
        copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
        free_metadata (&wpmd);
    }

    if (flags & HYBRID_FLAG) {
        write_hybrid_profile (wps, &wpmd);
        copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
        free_metadata (&wpmd);
    }

    if (flags & FLOAT_DATA) {
        write_float_info (wps, &wpmd);
        copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
        free_metadata (&wpmd);
    }

    if (flags & INT32_DATA) {
        write_int32_info (wps, &wpmd);
        copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
        free_metadata (&wpmd);
    }

    if ((flags & INITIAL_BLOCK) &&
        (wpc->config.num_channels > 2 ||
        wpc->config.channel_mask != 0x5 - wpc->config.num_channels)) {
            write_channel_info (wpc, &wpmd);
            copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
            free_metadata (&wpmd);
    }

    if ((flags & INITIAL_BLOCK) && !wps->sample_index) {
        write_config_info (wpc, &wpmd);
        copy_metadata (&wpmd, wps->blockbuff, wps->blockend);
        free_metadata (&wpmd);
    }

    bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend);

    if (wpc->wvc_flag) {
        wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
        memcpy (wps->block2buff, &wps->wphdr, sizeof (WavpackHeader));

        if (flags & HYBRID_SHAPE) {
            write_shaping_info (wps, &wpmd);
            copy_metadata (&wpmd, wps->block2buff, wps->block2end);
            free_metadata (&wpmd);
        }

        bs_open_write (&wps->wvcbits, wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 12, wps->block2end);
    }

    /////////////////////// handle lossless mono mode /////////////////////////

    if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA)) {
        if (!wps->num_passes)
            for (bptr = buffer, i = 0; i < sample_count; ++i) {
                int32_t code = *bptr;

                for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) {
                    int32_t sam;

                    if (dpp->term > MAX_TERM) {
                        if (dpp->term & 1)
                            sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
                        else
                            sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;

                        dpp->samples_A [1] = dpp->samples_A [0];
                        dpp->samples_A [0] = code;
                    }
                    else {
                        sam = dpp->samples_A [m];
                        dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = code;
                    }

                    code -= apply_weight (dpp->weight_A, sam);
                    update_weight (dpp->weight_A, dpp->delta, sam, code);
                }

                m = (m + 1) & (MAX_TERM - 1);
                *bptr++ = code;
            }

        send_words_lossless (wps, buffer, sample_count);
    }

    //////////////////// handle the lossless stereo mode //////////////////////

    else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) {
        int32_t *eptr = buffer + (sample_count * 2);

        if (!wps->num_passes) {
            if (flags & JOINT_STEREO)
                for (bptr = buffer; bptr < eptr; bptr += 2)
                    bptr [1] += ((bptr [0] -= bptr [1]) >> 1);

            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++)
                if (((flags & MAG_MASK) >> MAG_LSB) >= 16 || dpp->delta != 2)
                    decorr_stereo_pass (dpp, buffer, sample_count);
                else
                    decorr_stereo_pass_id2 (dpp, buffer, sample_count);
        }

        send_words_lossless (wps, buffer, sample_count);
    }

    /////////////////// handle the lossy/hybrid mono mode /////////////////////

    else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA))
        for (bptr = buffer, i = 0; i < sample_count; ++i) {
            int32_t code, temp;

            crc2 += (crc2 << 1) + (code = *bptr++);

            if (flags & HYBRID_SHAPE) {
                int shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
                temp = -apply_weight (shaping_weight, wps->dc.error [0]);

                if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) {
                    if (temp == wps->dc.error [0])
                        temp = (temp < 0) ? temp + 1 : temp - 1;

                    wps->dc.error [0] = -code;
                    code += temp;
                }
                else
                    wps->dc.error [0] = -(code += temp);
            }

            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++)
                if (dpp->term > MAX_TERM) {
                    if (dpp->term & 1)
                        dpp->samples_A [2] = 2 * dpp->samples_A [0] - dpp->samples_A [1];
                    else
                        dpp->samples_A [2] = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;

                    code -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [2]));
                }
                else
                    code -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [m]));

            code = send_word (wps, code, 0);

            while (--dpp >= wps->decorr_passes) {
                if (dpp->term > MAX_TERM) {
                    update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [2], code);
                    dpp->samples_A [1] = dpp->samples_A [0];
                    dpp->samples_A [0] = (code += dpp->aweight_A);
                }
                else {
                    int32_t sam = dpp->samples_A [m];

                    update_weight (dpp->weight_A, dpp->delta, sam, code);
                    dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = (code += dpp->aweight_A);
                }
            }

            wps->dc.error [0] += code;
            m = (m + 1) & (MAX_TERM - 1);

            if ((crc += (crc << 1) + code) != crc2)
                lossy = TRUE;

            if (wpc->config.flags & CONFIG_CALC_NOISE) {
                noise = code - bptr [-1];

                noise_acc += noise *= noise;
                wps->dc.noise_ave = (wps->dc.noise_ave * 0.99) + (noise * 0.01);

                if (wps->dc.noise_ave > wps->dc.noise_max)
                    wps->dc.noise_max = wps->dc.noise_ave;
            }
        }

    /////////////////// handle the lossy/hybrid stereo mode ///////////////////

    else if ((flags & HYBRID_FLAG) && !(flags & MONO_DATA))
        for (bptr = buffer, i = 0; i < sample_count; ++i) {
            int32_t left, right, temp;
            int shaping_weight;

            left = *bptr++;
            crc2 += (crc2 << 3) + (left << 1) + left + (right = *bptr++);

            if (flags & HYBRID_SHAPE) {
                shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16;
                temp = -apply_weight (shaping_weight, wps->dc.error [0]);

                if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) {
                    if (temp == wps->dc.error [0])
                        temp = (temp < 0) ? temp + 1 : temp - 1;

                    wps->dc.error [0] = -left;
                    left += temp;
                }
                else
                    wps->dc.error [0] = -(left += temp);

                shaping_weight = (wps->dc.shaping_acc [1] += wps->dc.shaping_delta [1]) >> 16;
                temp = -apply_weight (shaping_weight, wps->dc.error [1]);

                if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) {
                    if (temp == wps->dc.error [1])
                        temp = (temp < 0) ? temp + 1 : temp - 1;

                    wps->dc.error [1] = -right;
                    right += temp;
                }
                else
                    wps->dc.error [1] = -(right += temp);
            }

            if (flags & JOINT_STEREO)
                right += ((left -= right) >> 1);

            for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++)
                if (dpp->term > MAX_TERM) {
                    if (dpp->term & 1) {
                        dpp->samples_A [2] = 2 * dpp->samples_A [0] - dpp->samples_A [1];
                        dpp->samples_B [2] = 2 * dpp->samples_B [0] - dpp->samples_B [1];
                    }
                    else {
                        dpp->samples_A [2] = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1;
                        dpp->samples_B [2] = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1;
                    }

                    left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [2]));
                    right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [2]));
                }
                else if (dpp->term > 0) {
                    left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [m]));
                    right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [m]));
                }
                else {
                    if (dpp->term == -1)
                        dpp->samples_B [0] = left;
                    else if (dpp->term == -2)
                        dpp->samples_A [0] = right;

                    left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0]));
                    right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0]));
                }

            left = send_word (wps, left, 0);
            right = send_word (wps, right, 1);

            while (--dpp >= wps->decorr_passes)
                if (dpp->term > MAX_TERM) {
                    update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [2], left);
                    update_weight (dpp->weight_B, dpp->delta, dpp->samples_B [2], right);

                    dpp->samples_A [1] = dpp->samples_A [0];
                    dpp->samples_B [1] = dpp->samples_B [0];

                    dpp->samples_A [0] = (left += dpp->aweight_A);
                    dpp->samples_B [0] = (right += dpp->aweight_B);
                }
                else if (dpp->term > 0) {
                    int k = (m + dpp->term) & (MAX_TERM - 1);

                    update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [m], left);
                    dpp->samples_A [k] = (left += dpp->aweight_A);

                    update_weight (dpp->weight_B, dpp->delta, dpp->samples_B [m], right);
                    dpp->samples_B [k] = (right += dpp->aweight_B);
                }
                else {
                    if (dpp->term == -1) {
                        dpp->samples_B [0] = left + dpp->aweight_A;
                        dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0]);
                    }
                    else if (dpp->term == -2) {
                        dpp->samples_A [0] = right + dpp->aweight_B;
                        dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0]);
                    }

                    update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], left);
                    update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], right);
                    dpp->samples_B [0] = (left += dpp->aweight_A);
                    dpp->samples_A [0] = (right += dpp->aweight_B);
                }

            if (flags & JOINT_STEREO)
                left += (right -= (left >> 1));

            wps->dc.error [0] += left;
            wps->dc.error [1] += right;
            m = (m + 1) & (MAX_TERM - 1);

            if ((crc += (crc << 3) + (left << 1) + left + right) != crc2)
                lossy = TRUE;

            if (wpc->config.flags & CONFIG_CALC_NOISE) {
                noise = (double)(left - bptr [-2]) * (left - bptr [-2]);
                noise += (double)(right - bptr [-1]) * (right - bptr [-1]);

                noise_acc += noise /= 2.0;
                wps->dc.noise_ave = (wps->dc.noise_ave * 0.99) + (noise * 0.01);

                if (wps->dc.noise_ave > wps->dc.noise_max)
                    wps->dc.noise_max = wps->dc.noise_ave;
            }
        }

    if (m)
        for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++)
            if (dpp->term > 0 && dpp->term <= MAX_TERM) {
                int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];
                int k;

                memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
                memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));

                for (k = 0; k < MAX_TERM; k++) {
                    dpp->samples_A [k] = temp_A [m];
                    dpp->samples_B [k] = temp_B [m];
                    m = (m + 1) & (MAX_TERM - 1);
                }
            }

    if (wpc->config.flags & CONFIG_CALC_NOISE)
        wps->dc.noise_sum += noise_acc;

    flush_word (wps);
    data_count = bs_close_write (&wps->wvbits);

    if (data_count) {
        if (data_count != (uint32_t) -1) {
            uchar *cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8;

            *cptr++ = ID_WV_BITSTREAM | ID_LARGE;
            *cptr++ = data_count >> 1;
            *cptr++ = data_count >> 9;
            *cptr++ = data_count >> 17;
            ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4;
        }
        else
            return FALSE;
    }

    ((WavpackHeader *) wps->blockbuff)->crc = crc;

    if (wpc->wvc_flag) {
        data_count = bs_close_write (&wps->wvcbits);

        if (data_count && lossy) {
            if (data_count != (uint32_t) -1) {
                uchar *cptr = wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 8;

                *cptr++ = ID_WVC_BITSTREAM | ID_LARGE;
                *cptr++ = data_count >> 1;
                *cptr++ = data_count >> 9;
                *cptr++ = data_count >> 17;
                ((WavpackHeader *) wps->block2buff)->ckSize += data_count + 4;
            }
            else
                return FALSE;
        }

        ((WavpackHeader *) wps->block2buff)->crc = crc2;
    }
    else if (lossy)
        wpc->lossy_blocks = TRUE;

    wps->sample_index += sample_count;
    return TRUE;
}

// Perform a pass of the stereo decorrelation as specified by the referenced
// dpp structure. This version is optimized for samples that can use the
// simple apply_weight macro (i.e. <= 16-bit audio) and for when the weight
// delta is 2 (which is the case with all the default, non -x modes). For
// cases that do not fit this model, the more general decorr_stereo_pass()
// is provided. Note that this function returns the dpp->samples_X[] values
// in the "normalized" positions for terms 1-8.

static void decorr_stereo_pass_id2 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
{
    int32_t *bptr, *eptr = buffer + (sample_count * 2);
    int m, k;

    switch (dpp->term) {
        case 17:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
                dpp->samples_A [1] = dpp->samples_A [0];
                bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam);
                update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp);

                sam = 2 * dpp->samples_B [0] - dpp->samples_B [1];
                dpp->samples_B [1] = dpp->samples_B [0];
                bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam);
                update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp);
            }

            break;

        case 18:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1);
                dpp->samples_A [1] = dpp->samples_A [0];
                bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam);
                update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp);

                sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1);
                dpp->samples_B [1] = dpp->samples_B [0];
                bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam);
                update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp);
            }

            break;

        default:
            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = dpp->samples_A [m];
                bptr [0] = tmp = (dpp->samples_A [k] = bptr [0]) - apply_weight_i (dpp->weight_A, sam);
                update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp);

                sam = dpp->samples_B [m];
                bptr [1] = tmp = (dpp->samples_B [k] = bptr [1]) - apply_weight_i (dpp->weight_B, sam);
                update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp);

                m = (m + 1) & (MAX_TERM - 1);
                k = (k + 1) & (MAX_TERM - 1);
            }

            if (m) {
                int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];

                memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
                memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));

                for (k = 0; k < MAX_TERM; k++) {
                    dpp->samples_A [k] = temp_A [m];
                    dpp->samples_B [k] = temp_B [m];
                    m = (m + 1) & (MAX_TERM - 1);
                }
            }

            break;

        case -1:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_A = dpp->samples_A [0];
                bptr [0] = tmp = (sam_B = bptr [0]) - apply_weight_i (dpp->weight_A, sam_A);
                update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp);

                bptr [1] = tmp = (dpp->samples_A [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam_B);
                update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp);
            }

            break;

        case -2:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_B = dpp->samples_B [0];
                bptr [1] = tmp = (sam_A = bptr [1]) - apply_weight_i (dpp->weight_B, sam_B);
                update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp);

                bptr [0] = tmp = (dpp->samples_B [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam_A);
                update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp);
            }

            break;

        case -3:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_A = dpp->samples_A [0];
                sam_B = dpp->samples_B [0];

                dpp->samples_A [0] = tmp = bptr [1];
                bptr [1] = tmp -= apply_weight_i (dpp->weight_B, sam_B);
                update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp);

                dpp->samples_B [0] = tmp = bptr [0];
                bptr [0] = tmp -= apply_weight_i (dpp->weight_A, sam_A);
                update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp);
            }

            break;
    }
}

// Perform a pass of the stereo decorrelation as specified by the referenced
// dpp structure. This function is provided in both a regular C version and
// an MMX version (using intrinsics) written by Joachim Henke. The MMX version
// is significantly faster when the sample data requires the full-resolution
// apply_weight macro. However, when the data is lower resolution (<= 16-bit)
// then the difference is slight (or the MMX is even slower), so for these
// cases the simpler decorr_stereo_pass_id2() is used. Note that this function
// returns the dpp->samples_X[] values in the "normalized" positions for
// terms 1-8.

#ifdef OPT_MMX

static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
{
    const __m64
        delta = _mm_set1_pi32 (dpp->delta),
        fill = _mm_set1_pi32 (0x7bff),
        mask = _mm_set1_pi32 (0x7fff),
        round = _mm_set1_pi32 (512),
        zero = _mm_set1_pi32 (0);
    __m64
        weight_AB = _mm_set_pi32 (restore_weight (store_weight (dpp->weight_B)), restore_weight (store_weight (dpp->weight_A))),
        left_right, sam_AB, tmp0, tmp1, samples_AB [MAX_TERM];
    int k, m = 0;

    for (k = 0; k < MAX_TERM; ++k) {
        ((int32_t *) samples_AB) [k * 2] = exp2s (log2s (dpp->samples_A [k]));
        ((int32_t *) samples_AB) [k * 2 + 1] = exp2s (log2s (dpp->samples_B [k]));
    }

    if (dpp->term > 0) {
        if (dpp->term == 17) {
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                tmp0 = samples_AB [0];
                sam_AB = _m_paddd (tmp0, tmp0);
                sam_AB = _m_psubd (sam_AB, samples_AB [1]);
                samples_AB [0] = left_right;
                samples_AB [1] = tmp0;

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pxor (sam_AB, left_right);
                tmp0 = _m_psradi (tmp0, 31);
                tmp1 = _m_pxor (delta, tmp0);
                tmp1 = _m_psubd (tmp1, tmp0);
                sam_AB = _m_pcmpeqd (sam_AB, zero);
                tmp0 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, sam_AB);
                tmp0 = _m_pandn (tmp0, tmp1);
                weight_AB = _m_paddd (weight_AB, tmp0);

                buffer += 2;
            }
        }
        else if (dpp->term == 18) {
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                tmp0 = samples_AB [0];
                sam_AB = _m_psubd (tmp0, samples_AB [1]);
                sam_AB = _m_psradi (sam_AB, 1);
                sam_AB = _m_paddd (sam_AB, tmp0);
                samples_AB [0] = left_right;
                samples_AB [1] = tmp0;

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pxor (sam_AB, left_right);
                tmp0 = _m_psradi (tmp0, 31);
                tmp1 = _m_pxor (delta, tmp0);
                tmp1 = _m_psubd (tmp1, tmp0);
                sam_AB = _m_pcmpeqd (sam_AB, zero);
                tmp0 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, sam_AB);
                tmp0 = _m_pandn (tmp0, tmp1);
                weight_AB = _m_paddd (weight_AB, tmp0);

                buffer += 2;
            }
        }
        else {
            k = dpp->term & (MAX_TERM - 1);
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                sam_AB = samples_AB [m];
                samples_AB [k] = left_right;

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pxor (sam_AB, left_right);
                tmp0 = _m_psradi (tmp0, 31);
                tmp1 = _m_pxor (delta, tmp0);
                tmp1 = _m_psubd (tmp1, tmp0);
                sam_AB = _m_pcmpeqd (sam_AB, zero);
                tmp0 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, sam_AB);
                tmp0 = _m_pandn (tmp0, tmp1);
                weight_AB = _m_paddd (weight_AB, tmp0);

                buffer += 2;
                k = (k + 1) & (MAX_TERM - 1);
                m = (m + 1) & (MAX_TERM - 1);
            }
        }
    }
    else {
        if (dpp->term == -1) {
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                sam_AB = samples_AB [0];
                samples_AB [0] = _m_punpckhdq (left_right, sam_AB);
                sam_AB = _m_punpckldq (sam_AB, left_right);

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pcmpeqd (sam_AB, zero);
                tmp1 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, tmp1);
                tmp0 = _m_pandn (tmp0, delta);
                sam_AB = _m_pxor (sam_AB, left_right);
                sam_AB = _m_psradi (sam_AB, 31);
                tmp1 = _m_psubd (fill, sam_AB);
                weight_AB = _m_pxor (weight_AB, sam_AB);
                weight_AB = _m_paddd (weight_AB, tmp1);
                weight_AB = _m_paddsw (weight_AB, tmp0);
                weight_AB = _m_psubd (weight_AB, tmp1);
                weight_AB = _m_pxor (weight_AB, sam_AB);

                buffer += 2;
            }
        }
        else if (dpp->term == -2) {
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                sam_AB = samples_AB [0];
                samples_AB [0] = _m_punpckldq (sam_AB, left_right);
                sam_AB = _m_punpckhdq (left_right, sam_AB);

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pcmpeqd (sam_AB, zero);
                tmp1 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, tmp1);
                tmp0 = _m_pandn (tmp0, delta);
                sam_AB = _m_pxor (sam_AB, left_right);
                sam_AB = _m_psradi (sam_AB, 31);
                tmp1 = _m_psubd (fill, sam_AB);
                weight_AB = _m_pxor (weight_AB, sam_AB);
                weight_AB = _m_paddd (weight_AB, tmp1);
                weight_AB = _m_paddsw (weight_AB, tmp0);
                weight_AB = _m_psubd (weight_AB, tmp1);
                weight_AB = _m_pxor (weight_AB, sam_AB);

                buffer += 2;
            }
        }
        else if (dpp->term == -3) {
            while (sample_count--) {
                left_right = *(__m64 *) buffer;
                sam_AB = samples_AB [0];
                tmp0 = _m_punpckhdq (left_right, left_right);
                samples_AB [0] = _m_punpckldq (tmp0, left_right);

                tmp0 = _m_paddd (sam_AB, sam_AB);
                tmp1 = _m_pand (sam_AB, mask);
                tmp0 = _m_psrldi (tmp0, 16);
                tmp1 = _m_pmaddwd (tmp1, weight_AB);
                tmp0 = _m_pmaddwd (tmp0, weight_AB);
                tmp1 = _m_paddd (tmp1, round);
                tmp0 = _m_pslldi (tmp0, 5);
                tmp1 = _m_psradi (tmp1, 10);
                left_right = _m_psubd (left_right, tmp0);
                left_right = _m_psubd (left_right, tmp1);

                *(__m64 *) buffer = left_right;

                tmp0 = _m_pcmpeqd (sam_AB, zero);
                tmp1 = _m_pcmpeqd (left_right, zero);
                tmp0 = _m_por (tmp0, tmp1);
                tmp0 = _m_pandn (tmp0, delta);
                sam_AB = _m_pxor (sam_AB, left_right);
                sam_AB = _m_psradi (sam_AB, 31);
                tmp1 = _m_psubd (fill, sam_AB);
                weight_AB = _m_pxor (weight_AB, sam_AB);
                weight_AB = _m_paddd (weight_AB, tmp1);
                weight_AB = _m_paddsw (weight_AB, tmp0);
                weight_AB = _m_psubd (weight_AB, tmp1);
                weight_AB = _m_pxor (weight_AB, sam_AB);

                buffer += 2;
            }
        }
    }

    dpp->weight_A = ((int32_t *) &weight_AB) [0];
    dpp->weight_B = ((int32_t *) &weight_AB) [1];

    for (k = 0; k < MAX_TERM; ++k) {
        dpp->samples_A [k] = ((int32_t *) samples_AB) [m * 2];
        dpp->samples_B [k] = ((int32_t *) samples_AB) [m * 2 + 1];
        m = (m + 1) & (MAX_TERM - 1);
    }

    _mm_empty ();
}

#else

static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count)
{
    int32_t *bptr, *eptr = buffer + (sample_count * 2);
    int m, k;

    switch (dpp->term) {
        case 17:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = 2 * dpp->samples_A [0] - dpp->samples_A [1];
                dpp->samples_A [1] = dpp->samples_A [0];
                bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight (dpp->weight_A, sam);
                update_weight (dpp->weight_A, dpp->delta, sam, tmp);

                sam = 2 * dpp->samples_B [0] - dpp->samples_B [1];
                dpp->samples_B [1] = dpp->samples_B [0];
                bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight (dpp->weight_B, sam);
                update_weight (dpp->weight_B, dpp->delta, sam, tmp);
            }

            break;

        case 18:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1);
                dpp->samples_A [1] = dpp->samples_A [0];
                bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight (dpp->weight_A, sam);
                update_weight (dpp->weight_A, dpp->delta, sam, tmp);

                sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1);
                dpp->samples_B [1] = dpp->samples_B [0];
                bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight (dpp->weight_B, sam);
                update_weight (dpp->weight_B, dpp->delta, sam, tmp);
            }

            break;

        default:
            for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam, tmp;

                sam = dpp->samples_A [m];
                bptr [0] = tmp = (dpp->samples_A [k] = bptr [0]) - apply_weight (dpp->weight_A, sam);
                update_weight (dpp->weight_A, dpp->delta, sam, tmp);

                sam = dpp->samples_B [m];
                bptr [1] = tmp = (dpp->samples_B [k] = bptr [1]) - apply_weight (dpp->weight_B, sam);
                update_weight (dpp->weight_B, dpp->delta, sam, tmp);

                m = (m + 1) & (MAX_TERM - 1);
                k = (k + 1) & (MAX_TERM - 1);
            }

            if (m) {
                int32_t temp_A [MAX_TERM], temp_B [MAX_TERM];

                memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A));
                memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B));

                for (k = 0; k < MAX_TERM; k++) {
                    dpp->samples_A [k] = temp_A [m];
                    dpp->samples_B [k] = temp_B [m];
                    m = (m + 1) & (MAX_TERM - 1);
                }
            }

            break;

        case -1:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_A = dpp->samples_A [0];
                bptr [0] = tmp = (sam_B = bptr [0]) - apply_weight (dpp->weight_A, sam_A);
                update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp);

                bptr [1] = tmp = (dpp->samples_A [0] = bptr [1]) - apply_weight (dpp->weight_B, sam_B);
                update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp);
            }

            break;

        case -2:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_B = dpp->samples_B [0];
                bptr [1] = tmp = (sam_A = bptr [1]) - apply_weight (dpp->weight_B, sam_B);
                update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp);

                bptr [0] = tmp = (dpp->samples_B [0] = bptr [0]) - apply_weight (dpp->weight_A, sam_A);
                update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp);
            }

            break;

        case -3:
            for (bptr = buffer; bptr < eptr; bptr += 2) {
                int32_t sam_A, sam_B, tmp;

                sam_A = dpp->samples_A [0];
                sam_B = dpp->samples_B [0];

                dpp->samples_A [0] = tmp = bptr [1];
                bptr [1] = tmp -= apply_weight (dpp->weight_B, sam_B);
                update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp);

                dpp->samples_B [0] = tmp = bptr [0];
                bptr [0] = tmp -= apply_weight (dpp->weight_A, sam_A);
                update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp);
            }

            break;
    }
}

#endif

//////////////////////////////////////////////////////////////////////////////
// This function returns the accumulated RMS noise as a double if the       //
// CALC_NOISE bit was set in the WavPack header. The peak noise can also be //
// returned if desired. See wavpack.c for the calculations required to      //
// convert this into decibels of noise below full scale.                    //
//////////////////////////////////////////////////////////////////////////////

double WavpackGetEncodedNoise (WavpackContext *wpc, double *peak)
{
    WavpackStream *wps = wpc->streams [wpc->current_stream];

    if (peak)
        *peak = wps->dc.noise_max;

    return wps->dc.noise_sum;
}

Generated by  Doxygen 1.6.0   Back to index