applied patch from Richie Nyhus to convert CRLF to LF, as it should be

This commit is contained in:
Magnus Auvinen 2008-11-29 06:39:22 +00:00
parent 61d18702f6
commit 4004d13b48
12 changed files with 3849 additions and 3849 deletions

View file

@ -1,461 +1,461 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
/* This is an assembly optimized version of the following WavPack function:
*
* void decorr_stereo_pass_cont (struct decorr_pass *dpp,
* long *buffer, long sample_count);
*
* It performs a single pass of stereo decorrelation on the provided buffer.
* Note that this version of the function requires that the 8 previous stereo
* samples are visible and correct. In other words, it ignores the "samples_*"
* fields in the decorr_pass structure and gets the history data directly
* from the buffer. It does, however, return the appropriate history samples
* to the decorr_pass structure before returning.
*
* This is written to work on a ARM7TDMI processor. This version only uses the
* 32-bit multiply-accumulate instruction and so will overflow with 24-bit
* WavPack files.
*/
.text
.align
.global decorr_stereo_pass_cont_arm
/*
* on entry:
*
* r0 = struct decorr_pass *dpp
* r1 = long *buffer
* r2 = long sample_count
*/
decorr_stereo_pass_cont_arm:
stmfd sp!, {r4 - r8, r10, r11, lr}
mov r5, r0 @ r5 = dpp
mov r11, #512 @ r11 = 512 for rounding
ldrsh r6, [r0, #2] @ r6 = dpp->delta
ldrsh r4, [r0, #4] @ r4 = dpp->weight_A
ldrsh r0, [r0, #6] @ r0 = dpp->weight_B
cmp r2, #0 @ exit if no samples to process
beq common_exit
add r7, r1, r2, asl #3 @ r7 = buffer ending position
ldrsh r2, [r5, #0] @ r2 = dpp->term
cmp r2, #0
bmi minus_term
ldr lr, [r1, #-16] @ load 2 sample history from buffer
ldr r10, [r1, #-12] @ for terms 2, 17, and 18
ldr r8, [r1, #-8]
ldr r3, [r1, #-4]
cmp r2, #17
beq term_17_loop
cmp r2, #18
beq term_18_loop
cmp r2, #2
beq term_2_loop
b term_default_loop @ else handle default (1-8, except 2)
minus_term:
mov r10, #1024 @ r10 = -1024 for weight clipping
rsb r10, r10, #0 @ (only used for negative terms)
cmn r2, #1
beq term_minus_1
cmn r2, #2
beq term_minus_2
cmn r2, #3
beq term_minus_3
b common_exit
/*
******************************************************************************
* Loop to handle term = 17 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_17_loop:
rsbs ip, lr, r8, asl #1 @ decorr value = (2 * prev) - 2nd prev
mov lr, r8 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L325
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L325: rsbs ip, r10, r3, asl #1 @ do same thing for right channel
mov r10, r3
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L329
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L329: cmp r7, r1 @ loop back if more samples to do
bhi term_17_loop
b store_1718 @ common exit for terms 17 & 18
/*
******************************************************************************
* Loop to handle term = 18 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_18_loop:
sub ip, r8, lr @ decorr value =
mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1
adds ip, r8, ip, asr #1
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L337
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L337: sub ip, r3, r10 @ do same thing for right channel
mov r10, r3
adds ip, r3, ip, asr #1
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L341
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L341: cmp r7, r1 @ loop back if more samples to do
bhi term_18_loop
/* common exit for terms 17 & 18 */
store_1718:
str r3, [r5, #40] @ store sample history into struct
str r8, [r5, #8]
str r10, [r5, #44]
str lr, [r5, #12]
b common_exit @ and return
/*
******************************************************************************
* Loop to handle term = 2 condition
* (note that this case can be handled by the default term handler (1-8), but
* this special case is faster because it doesn't have to read memory twice)
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_2_loop:
movs ip, lr @ get decorrelation value & test
mov lr, r8 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L225
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L225: movs ip, r10 @ do same thing for right channel
mov r10, r3
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L229
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L229: cmp r7, r1 @ loop back if more samples to do
bhi term_2_loop
b default_term_exit @ this exit updates all dpp->samples
/*
******************************************************************************
* Loop to handle default term condition
*
* r0 = dpp->weight_B r8 = result accumulator
* r1 = bptr r9 =
* r2 = dpp->term r10 =
* r3 = decorrelation value r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_default_loop:
ldr ip, [r1] @ get original sample
ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term
mla r8, r3, r4, r11 @ mult decorr value by weight, round,
add r8, ip, r8, asr #10 @ shift and add to new sample
str r8, [r1], #4 @ store update sample
cmp r3, #0
cmpne ip, #0
beq .L350
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L350: ldr ip, [r1] @ do the same thing for right channel
ldr r3, [r1, -r2, asl #3]
mla r8, r3, r0, r11
add r8, ip, r8, asr #10
str r8, [r1], #4
cmp r3, #0
cmpne ip, #0
beq .L354
teq ip, r3
submi r0, r0, r6
addpl r0, r0, r6
.L354: cmp r7, r1 @ loop back if more samples to do
bhi term_default_loop
/*
* This exit is used by terms 1-8 to store the previous 8 samples into the decorr
* structure (even if they are not all used for the given term)
*/
default_term_exit:
ldrsh r3, [r5, #0]
sub ip, r3, #1
mov lr, #7
.L358: and r3, ip, #7
add r3, r5, r3, asl #2
ldr r2, [r1, #-4]
str r2, [r3, #40]
ldr r2, [r1, #-8]!
str r2, [r3, #8]
sub ip, ip, #1
sub lr, lr, #1
cmn lr, #1
bne .L358
b common_exit
/*
******************************************************************************
* Loop to handle term = -1 condition
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated left sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_1:
ldr r3, [r1, #-4]
term_minus_1_loop:
ldr ip, [r1] @ for left channel the decorrelation value
mla r2, r3, r4, r11 @ is the previous right sample (in r3)
add lr, ip, r2, asr #10
str lr, [r1], #8
cmp r3, #0
cmpne ip, #0
beq .L361
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value
mla r3, lr, r0, r11 @ is the just updated right sample (in lr)
add r3, r2, r3, asr #10
str r3, [r1, #-4]
cmp lr, #0
cmpne r2, #0
beq .L369
teq r2, lr
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024 @ then clip weight to +/-1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L369: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_1_loop
str r3, [r5, #8] @ else store right sample and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -2 condition
* (note that the channels are processed in the reverse order here)
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous left sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_2:
ldr r3, [r1, #-8]
term_minus_2_loop:
ldr ip, [r1, #4] @ for right channel the decorrelation value
mla r2, r3, r0, r11 @ is the previous left sample (in r3)
add lr, ip, r2, asr #10
str lr, [r1, #4]
cmp r3, #0
cmpne ip, #0
beq .L380
teq ip, r3 @ update weight based on signs
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024 @ then clip weight to +/-1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L380: ldr r2, [r1, #0] @ for left channel the decorrelation value
mla r3, lr, r4, r11 @ is the just updated left sample (in lr)
add r3, r2, r3, asr #10
str r3, [r1], #8
cmp lr, #0
cmpne r2, #0
beq .L388
teq r2, lr
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L388: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_2_loop
str r3, [r5, #40] @ else store left channel and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -3 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current left sample r10 = -1024 (for clipping)
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = intermediate result
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_3:
ldr r3, [r1, #-4] @ load previous samples
ldr r8, [r1, #-8]
term_minus_3_loop:
ldr ip, [r1]
mla r2, r3, r4, r11
add r2, ip, r2, asr #10
str r2, [r1], #4
cmp r3, #0
cmpne ip, #0
beq .L399
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024 @ then clip weight to +/-1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L399: movs ip, r8 @ ip = previous left we use now
mov r8, r2 @ r8 = current left we use next time
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L407
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L407: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_3_loop
str r3, [r5, #8] @ else store previous samples & exit
str r8, [r5, #40]
/*
* Before finally exiting we must store weights back for next time
*/
common_exit:
strh r4, [r5, #4]
strh r0, [r5, #6]
ldmfd sp!, {r4 - r8, r10, r11, pc}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
/* This is an assembly optimized version of the following WavPack function:
*
* void decorr_stereo_pass_cont (struct decorr_pass *dpp,
* long *buffer, long sample_count);
*
* It performs a single pass of stereo decorrelation on the provided buffer.
* Note that this version of the function requires that the 8 previous stereo
* samples are visible and correct. In other words, it ignores the "samples_*"
* fields in the decorr_pass structure and gets the history data directly
* from the buffer. It does, however, return the appropriate history samples
* to the decorr_pass structure before returning.
*
* This is written to work on a ARM7TDMI processor. This version only uses the
* 32-bit multiply-accumulate instruction and so will overflow with 24-bit
* WavPack files.
*/
.text
.align
.global decorr_stereo_pass_cont_arm
/*
* on entry:
*
* r0 = struct decorr_pass *dpp
* r1 = long *buffer
* r2 = long sample_count
*/
decorr_stereo_pass_cont_arm:
stmfd sp!, {r4 - r8, r10, r11, lr}
mov r5, r0 @ r5 = dpp
mov r11, #512 @ r11 = 512 for rounding
ldrsh r6, [r0, #2] @ r6 = dpp->delta
ldrsh r4, [r0, #4] @ r4 = dpp->weight_A
ldrsh r0, [r0, #6] @ r0 = dpp->weight_B
cmp r2, #0 @ exit if no samples to process
beq common_exit
add r7, r1, r2, asl #3 @ r7 = buffer ending position
ldrsh r2, [r5, #0] @ r2 = dpp->term
cmp r2, #0
bmi minus_term
ldr lr, [r1, #-16] @ load 2 sample history from buffer
ldr r10, [r1, #-12] @ for terms 2, 17, and 18
ldr r8, [r1, #-8]
ldr r3, [r1, #-4]
cmp r2, #17
beq term_17_loop
cmp r2, #18
beq term_18_loop
cmp r2, #2
beq term_2_loop
b term_default_loop @ else handle default (1-8, except 2)
minus_term:
mov r10, #1024 @ r10 = -1024 for weight clipping
rsb r10, r10, #0 @ (only used for negative terms)
cmn r2, #1
beq term_minus_1
cmn r2, #2
beq term_minus_2
cmn r2, #3
beq term_minus_3
b common_exit
/*
******************************************************************************
* Loop to handle term = 17 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_17_loop:
rsbs ip, lr, r8, asl #1 @ decorr value = (2 * prev) - 2nd prev
mov lr, r8 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L325
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L325: rsbs ip, r10, r3, asl #1 @ do same thing for right channel
mov r10, r3
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L329
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L329: cmp r7, r1 @ loop back if more samples to do
bhi term_17_loop
b store_1718 @ common exit for terms 17 & 18
/*
******************************************************************************
* Loop to handle term = 18 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_18_loop:
sub ip, r8, lr @ decorr value =
mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1
adds ip, r8, ip, asr #1
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L337
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L337: sub ip, r3, r10 @ do same thing for right channel
mov r10, r3
adds ip, r3, ip, asr #1
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L341
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L341: cmp r7, r1 @ loop back if more samples to do
bhi term_18_loop
/* common exit for terms 17 & 18 */
store_1718:
str r3, [r5, #40] @ store sample history into struct
str r8, [r5, #8]
str r10, [r5, #44]
str lr, [r5, #12]
b common_exit @ and return
/*
******************************************************************************
* Loop to handle term = 2 condition
* (note that this case can be handled by the default term handler (1-8), but
* this special case is faster because it doesn't have to read memory twice)
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_2_loop:
movs ip, lr @ get decorrelation value & test
mov lr, r8 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mla r8, ip, r4, r11 @ mult decorr value by weight, round,
add r8, r2, r8, asr #10 @ shift, and add to new sample
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L225
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L225: movs ip, r10 @ do same thing for right channel
mov r10, r3
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L229
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L229: cmp r7, r1 @ loop back if more samples to do
bhi term_2_loop
b default_term_exit @ this exit updates all dpp->samples
/*
******************************************************************************
* Loop to handle default term condition
*
* r0 = dpp->weight_B r8 = result accumulator
* r1 = bptr r9 =
* r2 = dpp->term r10 =
* r3 = decorrelation value r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_default_loop:
ldr ip, [r1] @ get original sample
ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term
mla r8, r3, r4, r11 @ mult decorr value by weight, round,
add r8, ip, r8, asr #10 @ shift and add to new sample
str r8, [r1], #4 @ store update sample
cmp r3, #0
cmpne ip, #0
beq .L350
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L350: ldr ip, [r1] @ do the same thing for right channel
ldr r3, [r1, -r2, asl #3]
mla r8, r3, r0, r11
add r8, ip, r8, asr #10
str r8, [r1], #4
cmp r3, #0
cmpne ip, #0
beq .L354
teq ip, r3
submi r0, r0, r6
addpl r0, r0, r6
.L354: cmp r7, r1 @ loop back if more samples to do
bhi term_default_loop
/*
* This exit is used by terms 1-8 to store the previous 8 samples into the decorr
* structure (even if they are not all used for the given term)
*/
default_term_exit:
ldrsh r3, [r5, #0]
sub ip, r3, #1
mov lr, #7
.L358: and r3, ip, #7
add r3, r5, r3, asl #2
ldr r2, [r1, #-4]
str r2, [r3, #40]
ldr r2, [r1, #-8]!
str r2, [r3, #8]
sub ip, ip, #1
sub lr, lr, #1
cmn lr, #1
bne .L358
b common_exit
/*
******************************************************************************
* Loop to handle term = -1 condition
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated left sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_1:
ldr r3, [r1, #-4]
term_minus_1_loop:
ldr ip, [r1] @ for left channel the decorrelation value
mla r2, r3, r4, r11 @ is the previous right sample (in r3)
add lr, ip, r2, asr #10
str lr, [r1], #8
cmp r3, #0
cmpne ip, #0
beq .L361
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value
mla r3, lr, r0, r11 @ is the just updated right sample (in lr)
add r3, r2, r3, asr #10
str r3, [r1, #-4]
cmp lr, #0
cmpne r2, #0
beq .L369
teq r2, lr
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024 @ then clip weight to +/-1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L369: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_1_loop
str r3, [r5, #8] @ else store right sample and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -2 condition
* (note that the channels are processed in the reverse order here)
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous left sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_2:
ldr r3, [r1, #-8]
term_minus_2_loop:
ldr ip, [r1, #4] @ for right channel the decorrelation value
mla r2, r3, r0, r11 @ is the previous left sample (in r3)
add lr, ip, r2, asr #10
str lr, [r1, #4]
cmp r3, #0
cmpne ip, #0
beq .L380
teq ip, r3 @ update weight based on signs
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024 @ then clip weight to +/-1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L380: ldr r2, [r1, #0] @ for left channel the decorrelation value
mla r3, lr, r4, r11 @ is the just updated left sample (in lr)
add r3, r2, r3, asr #10
str r3, [r1], #8
cmp lr, #0
cmpne r2, #0
beq .L388
teq r2, lr
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L388: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_2_loop
str r3, [r5, #40] @ else store left channel and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -3 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current left sample r10 = -1024 (for clipping)
* r3 = previous right sample r11 = 512 (for rounding)
* r4 = dpp->weight_A ip = intermediate result
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_3:
ldr r3, [r1, #-4] @ load previous samples
ldr r8, [r1, #-8]
term_minus_3_loop:
ldr ip, [r1]
mla r2, r3, r4, r11
add r2, ip, r2, asr #10
str r2, [r1], #4
cmp r3, #0
cmpne ip, #0
beq .L399
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #1024 @ then clip weight to +/-1024
movgt r4, #1024
cmp r4, r10
movlt r4, r10
.L399: movs ip, r8 @ ip = previous left we use now
mov r8, r2 @ r8 = current left we use next time
ldr r2, [r1], #4
mla r3, ip, r0, r11
add r3, r2, r3, asr #10
strne r3, [r1, #-4]
cmpne r2, #0
beq .L407
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #1024
movgt r0, #1024
cmp r0, r10
movlt r0, r10
.L407: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_3_loop
str r3, [r5, #8] @ else store previous samples & exit
str r8, [r5, #40]
/*
* Before finally exiting we must store weights back for next time
*/
common_exit:
strh r4, [r5, #4]
strh r0, [r5, #6]
ldmfd sp!, {r4 - r8, r10, r11, pc}

View file

@ -1,491 +1,491 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
/* This is an assembly optimized version of the following WavPack function:
*
* void decorr_stereo_pass_cont (struct decorr_pass *dpp,
* long *buffer, long sample_count);
*
* It performs a single pass of stereo decorrelation on the provided buffer.
* Note that this version of the function requires that the 8 previous stereo
* samples are visible and correct. In other words, it ignores the "samples_*"
* fields in the decorr_pass structure and gets the history data directly
* from the buffer. It does, however, return the appropriate history samples
* to the decorr_pass structure before returning.
*
* This is written to work on a ARM7TDMI processor. This version uses the
* 64-bit multiply-accumulate instruction and so can be used with all
* WavPack files. However, for optimum performance with 16-bit WavPack
* files, there is a faster version that only uses the 32-bit MLA
* instruction.
*/
.text
.align
.global decorr_stereo_pass_cont_arml
/*
* on entry:
*
* r0 = struct decorr_pass *dpp
* r1 = long *buffer
* r2 = long sample_count
*/
decorr_stereo_pass_cont_arml:
stmfd sp!, {r4 - r8, r10, r11, lr}
mov r5, r0 @ r5 = dpp
mov r11, #512 @ r11 = 512 for rounding
ldrsh r6, [r0, #2] @ r6 = dpp->delta
ldrsh r4, [r0, #4] @ r4 = dpp->weight_A
ldrsh r0, [r0, #6] @ r0 = dpp->weight_B
cmp r2, #0 @ exit if no samples to process
beq common_exit
mov r0, r0, asl #18 @ for 64-bit math we use weights << 18
mov r4, r4, asl #18
mov r6, r6, asl #18
add r7, r1, r2, asl #3 @ r7 = buffer ending position
ldrsh r2, [r5, #0] @ r2 = dpp->term
cmp r2, #0
blt minus_term
ldr lr, [r1, #-16] @ load 2 sample history from buffer
ldr r10, [r1, #-12] @ for terms 2, 17, and 18
ldr r8, [r1, #-8]
ldr r3, [r1, #-4]
cmp r2, #18
beq term_18_loop
mov lr, lr, asl #4
mov r10, r10, asl #4
cmp r2, #2
beq term_2_loop
cmp r2, #17
beq term_17_loop
b term_default_loop
minus_term:
mov r10, #(1024 << 18) @ r10 = -1024 << 18 for weight clipping
rsb r10, r10, #0 @ (only used for negative terms)
cmn r2, #1
beq term_minus_1
cmn r2, #2
beq term_minus_2
cmn r2, #3
beq term_minus_3
b common_exit
/*
******************************************************************************
* Loop to handle term = 17 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample << 4
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample << 4
* r7 = eptr pc =
*******************************************************************************
*/
term_17_loop:
rsbs ip, lr, r8, asl #5 @ decorr value = (2 * prev) - 2nd prev
mov lr, r8, asl #4 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L325
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L325: rsbs ip, r10, r3, asl #5 @ do same thing for right channel
mov r10, r3, asl #4
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L329
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L329: cmp r7, r1 @ loop back if more samples to do
bhi term_17_loop
mov lr, lr, asr #4
mov r10, r10, asr #4
b store_1718 @ common exit for terms 17 & 18
/*
******************************************************************************
* Loop to handle term = 18 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_18_loop:
rsb ip, lr, r8 @ decorr value =
mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1
add ip, lr, ip, asr #1
movs ip, ip, asl #4
ldr r2, [r1], #4 @ get sample & update pointer
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L337
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L337: rsb ip, r10, r3 @ do same thing for right channel
mov r10, r3
add ip, r10, ip, asr #1
movs ip, ip, asl #4
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L341
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L341: cmp r7, r1 @ loop back if more samples to do
bhi term_18_loop
/* common exit for terms 17 & 18 */
store_1718:
str r3, [r5, #40] @ store sample history into struct
str r8, [r5, #8]
str r10, [r5, #44]
str lr, [r5, #12]
b common_exit @ and return
/*
******************************************************************************
* Loop to handle term = 2 condition
* (note that this case can be handled by the default term handler (1-8), but
* this special case is faster because it doesn't have to read memory twice)
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample << 4
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample << 4
* r7 = eptr pc =
*******************************************************************************
*/
term_2_loop:
movs ip, lr @ get decorrelation value & test
ldr r2, [r1], #4 @ get sample & update pointer
mov lr, r8, asl #4 @ previous becomes 2nd previous
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L225
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L225: movs ip, r10 @ do same thing for right channel
ldr r2, [r1], #4
mov r10, r3, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L229
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L229: cmp r7, r1 @ loop back if more samples to do
bhi term_2_loop
b default_term_exit @ this exit updates all dpp->samples
/*
******************************************************************************
* Loop to handle default term condition
*
* r0 = dpp->weight_B r8 = result accumulator
* r1 = bptr r9 =
* r2 = dpp->term r10 =
* r3 = decorrelation value r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_default_loop:
ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term
ldr ip, [r1], #4 @ get original sample and bump ptr
movs r3, r3, asl #4
mov r11, #0x80000000
mov r8, ip
smlalne r11, r8, r4, r3
strne r8, [r1, #-4] @ if possibly changed, store updated sample
cmpne ip, #0
beq .L350
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L350: ldr r3, [r1, -r2, asl #3] @ do the same thing for right channel
ldr ip, [r1], #4
movs r3, r3, asl #4
mov r11, #0x80000000
mov r8, ip
smlalne r11, r8, r0, r3
strne r8, [r1, #-4]
cmpne ip, #0
beq .L354
teq ip, r3
submi r0, r0, r6
addpl r0, r0, r6
.L354: cmp r7, r1 @ loop back if more samples to do
bhi term_default_loop
/*
* This exit is used by terms 1-8 to store the previous 8 samples into the decorr
* structure (even if they are not all used for the given term)
*/
default_term_exit:
ldrsh r3, [r5, #0]
sub ip, r3, #1
mov lr, #7
.L358: and r3, ip, #7
add r3, r5, r3, asl #2
ldr r2, [r1, #-4]
str r2, [r3, #40]
ldr r2, [r1, #-8]!
str r2, [r3, #8]
sub ip, ip, #1
sub lr, lr, #1
cmn lr, #1
bne .L358
b common_exit
/*
******************************************************************************
* Loop to handle term = -1 condition
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated left sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_1:
ldr r3, [r1, #-4]
term_minus_1_loop:
ldr ip, [r1], #8 @ for left channel the decorrelation value
movs r3, r3, asl #4 @ is the previous right sample (in r3)
mov r11, #0x80000000
mov lr, ip
smlalne r11, lr, r4, r3
strne lr, [r1, #-8]
cmpne ip, #0
beq .L361
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18)
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value
movs lr, lr, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, lr
strne r3, [r1, #-4]
cmpne r2, #0
beq .L369
teq r2, lr
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18) @ then clip weight to +/-1024
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L369: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_1_loop
str r3, [r5, #8] @ else store right sample and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -2 condition
* (note that the channels are processed in the reverse order here)
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous left sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_2:
ldr r3, [r1, #-8]
term_minus_2_loop:
ldr ip, [r1, #4] @ for right channel the decorrelation value
movs r3, r3, asl #4 @ is the previous left sample (in r3)
mov r11, #0x80000000
mov lr, ip
smlalne r11, lr, r0, r3
strne lr, [r1, #4]
cmpne ip, #0
beq .L380
teq ip, r3 @ update weight based on signs
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18) @ then clip weight to +/-1024
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L380: ldr r2, [r1], #8 @ for left channel the decorrelation value
movs lr, lr, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r4, lr
strne r3, [r1, #-8]
cmpne r2, #0
beq .L388
teq r2, lr
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18)
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L388: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_2_loop
str r3, [r5, #40] @ else store left channel and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -3 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current left sample r10 = -1024 (for clipping)
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = intermediate result
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_3:
ldr r3, [r1, #-4] @ load previous samples
ldr r8, [r1, #-8]
term_minus_3_loop:
ldr ip, [r1], #4
movs r3, r3, asl #4
mov r11, #0x80000000
mov r2, ip
smlalne r11, r2, r4, r3
strne r2, [r1, #-4]
cmpne ip, #0
beq .L399
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18) @ then clip weight to +/-1024
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L399: movs ip, r8, asl #4 @ ip = previous left we use now
mov r8, r2 @ r8 = current left we use next time
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L407
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18)
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L407: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_3_loop
str r3, [r5, #8] @ else store previous samples & exit
str r8, [r5, #40]
/*
* Before finally exiting we must store weights back for next time
*/
common_exit:
mov r0, r0, asr #18 @ restore weights to real magnitude
mov r4, r4, asr #18
strh r4, [r5, #4]
strh r0, [r5, #6]
ldmfd sp!, {r4 - r8, r10, r11, pc}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
/* This is an assembly optimized version of the following WavPack function:
*
* void decorr_stereo_pass_cont (struct decorr_pass *dpp,
* long *buffer, long sample_count);
*
* It performs a single pass of stereo decorrelation on the provided buffer.
* Note that this version of the function requires that the 8 previous stereo
* samples are visible and correct. In other words, it ignores the "samples_*"
* fields in the decorr_pass structure and gets the history data directly
* from the buffer. It does, however, return the appropriate history samples
* to the decorr_pass structure before returning.
*
* This is written to work on a ARM7TDMI processor. This version uses the
* 64-bit multiply-accumulate instruction and so can be used with all
* WavPack files. However, for optimum performance with 16-bit WavPack
* files, there is a faster version that only uses the 32-bit MLA
* instruction.
*/
.text
.align
.global decorr_stereo_pass_cont_arml
/*
* on entry:
*
* r0 = struct decorr_pass *dpp
* r1 = long *buffer
* r2 = long sample_count
*/
decorr_stereo_pass_cont_arml:
stmfd sp!, {r4 - r8, r10, r11, lr}
mov r5, r0 @ r5 = dpp
mov r11, #512 @ r11 = 512 for rounding
ldrsh r6, [r0, #2] @ r6 = dpp->delta
ldrsh r4, [r0, #4] @ r4 = dpp->weight_A
ldrsh r0, [r0, #6] @ r0 = dpp->weight_B
cmp r2, #0 @ exit if no samples to process
beq common_exit
mov r0, r0, asl #18 @ for 64-bit math we use weights << 18
mov r4, r4, asl #18
mov r6, r6, asl #18
add r7, r1, r2, asl #3 @ r7 = buffer ending position
ldrsh r2, [r5, #0] @ r2 = dpp->term
cmp r2, #0
blt minus_term
ldr lr, [r1, #-16] @ load 2 sample history from buffer
ldr r10, [r1, #-12] @ for terms 2, 17, and 18
ldr r8, [r1, #-8]
ldr r3, [r1, #-4]
cmp r2, #18
beq term_18_loop
mov lr, lr, asl #4
mov r10, r10, asl #4
cmp r2, #2
beq term_2_loop
cmp r2, #17
beq term_17_loop
b term_default_loop
minus_term:
mov r10, #(1024 << 18) @ r10 = -1024 << 18 for weight clipping
rsb r10, r10, #0 @ (only used for negative terms)
cmn r2, #1
beq term_minus_1
cmn r2, #2
beq term_minus_2
cmn r2, #3
beq term_minus_3
b common_exit
/*
******************************************************************************
* Loop to handle term = 17 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample << 4
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample << 4
* r7 = eptr pc =
*******************************************************************************
*/
term_17_loop:
rsbs ip, lr, r8, asl #5 @ decorr value = (2 * prev) - 2nd prev
mov lr, r8, asl #4 @ previous becomes 2nd previous
ldr r2, [r1], #4 @ get sample & update pointer
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L325
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L325: rsbs ip, r10, r3, asl #5 @ do same thing for right channel
mov r10, r3, asl #4
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L329
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L329: cmp r7, r1 @ loop back if more samples to do
bhi term_17_loop
mov lr, lr, asr #4
mov r10, r10, asr #4
b store_1718 @ common exit for terms 17 & 18
/*
******************************************************************************
* Loop to handle term = 18 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_18_loop:
rsb ip, lr, r8 @ decorr value =
mov lr, r8 @ ((3 * prev) - 2nd prev) >> 1
add ip, lr, ip, asr #1
movs ip, ip, asl #4
ldr r2, [r1], #4 @ get sample & update pointer
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L337
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L337: rsb ip, r10, r3 @ do same thing for right channel
mov r10, r3
add ip, r10, ip, asr #1
movs ip, ip, asl #4
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L341
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L341: cmp r7, r1 @ loop back if more samples to do
bhi term_18_loop
/* common exit for terms 17 & 18 */
store_1718:
str r3, [r5, #40] @ store sample history into struct
str r8, [r5, #8]
str r10, [r5, #44]
str lr, [r5, #12]
b common_exit @ and return
/*
******************************************************************************
* Loop to handle term = 2 condition
* (note that this case can be handled by the default term handler (1-8), but
* this special case is faster because it doesn't have to read memory twice)
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current sample r10 = second previous left sample << 4
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = decorrelation value
* r5 = dpp sp =
* r6 = dpp->delta lr = second previous right sample << 4
* r7 = eptr pc =
*******************************************************************************
*/
term_2_loop:
movs ip, lr @ get decorrelation value & test
ldr r2, [r1], #4 @ get sample & update pointer
mov lr, r8, asl #4 @ previous becomes 2nd previous
mov r11, #0x80000000
mov r8, r2
smlalne r11, r8, r4, ip
strne r8, [r1, #-4] @ if change possible, store sample back
cmpne r2, #0
beq .L225
teq ip, r2 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L225: movs ip, r10 @ do same thing for right channel
ldr r2, [r1], #4
mov r10, r3, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L229
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
.L229: cmp r7, r1 @ loop back if more samples to do
bhi term_2_loop
b default_term_exit @ this exit updates all dpp->samples
/*
******************************************************************************
* Loop to handle default term condition
*
* r0 = dpp->weight_B r8 = result accumulator
* r1 = bptr r9 =
* r2 = dpp->term r10 =
* r3 = decorrelation value r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_default_loop:
ldr r3, [r1, -r2, asl #3] @ get decorrelation value based on term
ldr ip, [r1], #4 @ get original sample and bump ptr
movs r3, r3, asl #4
mov r11, #0x80000000
mov r8, ip
smlalne r11, r8, r4, r3
strne r8, [r1, #-4] @ if possibly changed, store updated sample
cmpne ip, #0
beq .L350
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
.L350: ldr r3, [r1, -r2, asl #3] @ do the same thing for right channel
ldr ip, [r1], #4
movs r3, r3, asl #4
mov r11, #0x80000000
mov r8, ip
smlalne r11, r8, r0, r3
strne r8, [r1, #-4]
cmpne ip, #0
beq .L354
teq ip, r3
submi r0, r0, r6
addpl r0, r0, r6
.L354: cmp r7, r1 @ loop back if more samples to do
bhi term_default_loop
/*
* This exit is used by terms 1-8 to store the previous 8 samples into the decorr
* structure (even if they are not all used for the given term)
*/
default_term_exit:
ldrsh r3, [r5, #0]
sub ip, r3, #1
mov lr, #7
.L358: and r3, ip, #7
add r3, r5, r3, asl #2
ldr r2, [r1, #-4]
str r2, [r3, #40]
ldr r2, [r1, #-8]!
str r2, [r3, #8]
sub ip, ip, #1
sub lr, lr, #1
cmn lr, #1
bne .L358
b common_exit
/*
******************************************************************************
* Loop to handle term = -1 condition
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated left sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_1:
ldr r3, [r1, #-4]
term_minus_1_loop:
ldr ip, [r1], #8 @ for left channel the decorrelation value
movs r3, r3, asl #4 @ is the previous right sample (in r3)
mov r11, #0x80000000
mov lr, ip
smlalne r11, lr, r4, r3
strne lr, [r1, #-8]
cmpne ip, #0
beq .L361
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18)
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L361: ldr r2, [r1, #-4] @ for right channel the decorrelation value
movs lr, lr, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, lr
strne r3, [r1, #-4]
cmpne r2, #0
beq .L369
teq r2, lr
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18) @ then clip weight to +/-1024
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L369: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_1_loop
str r3, [r5, #8] @ else store right sample and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -2 condition
* (note that the channels are processed in the reverse order here)
*
* r0 = dpp->weight_B r8 =
* r1 = bptr r9 =
* r2 = intermediate result r10 = -1024 (for clipping)
* r3 = previous left sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = current sample
* r5 = dpp sp =
* r6 = dpp->delta lr = updated right sample
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_2:
ldr r3, [r1, #-8]
term_minus_2_loop:
ldr ip, [r1, #4] @ for right channel the decorrelation value
movs r3, r3, asl #4 @ is the previous left sample (in r3)
mov r11, #0x80000000
mov lr, ip
smlalne r11, lr, r0, r3
strne lr, [r1, #4]
cmpne ip, #0
beq .L380
teq ip, r3 @ update weight based on signs
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18) @ then clip weight to +/-1024
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L380: ldr r2, [r1], #8 @ for left channel the decorrelation value
movs lr, lr, asl #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r4, lr
strne r3, [r1, #-8]
cmpne r2, #0
beq .L388
teq r2, lr
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18)
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L388: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_2_loop
str r3, [r5, #40] @ else store left channel and exit
b common_exit
/*
******************************************************************************
* Loop to handle term = -3 condition
*
* r0 = dpp->weight_B r8 = previous left sample
* r1 = bptr r9 =
* r2 = current left sample r10 = -1024 (for clipping)
* r3 = previous right sample r11 = lo accumulator (for rounding)
* r4 = dpp->weight_A ip = intermediate result
* r5 = dpp sp =
* r6 = dpp->delta lr =
* r7 = eptr pc =
*******************************************************************************
*/
term_minus_3:
ldr r3, [r1, #-4] @ load previous samples
ldr r8, [r1, #-8]
term_minus_3_loop:
ldr ip, [r1], #4
movs r3, r3, asl #4
mov r11, #0x80000000
mov r2, ip
smlalne r11, r2, r4, r3
strne r2, [r1, #-4]
cmpne ip, #0
beq .L399
teq ip, r3 @ update weight based on signs
submi r4, r4, r6
addpl r4, r4, r6
cmp r4, #(1024 << 18) @ then clip weight to +/-1024
movgt r4, #(1024 << 18)
cmp r4, r10
movlt r4, r10
.L399: movs ip, r8, asl #4 @ ip = previous left we use now
mov r8, r2 @ r8 = current left we use next time
ldr r2, [r1], #4
mov r11, #0x80000000
mov r3, r2
smlalne r11, r3, r0, ip
strne r3, [r1, #-4]
cmpne r2, #0
beq .L407
teq ip, r2
submi r0, r0, r6
addpl r0, r0, r6
cmp r0, #(1024 << 18)
movgt r0, #(1024 << 18)
cmp r0, r10
movlt r0, r10
.L407: cmp r7, r1 @ loop back if more samples to do
bhi term_minus_3_loop
str r3, [r5, #8] @ else store previous samples & exit
str r8, [r5, #40]
/*
* Before finally exiting we must store weights back for next time
*/
common_exit:
mov r0, r0, asr #18 @ restore weights to real magnitude
mov r4, r4, asr #18
strh r4, [r5, #4]
strh r0, [r5, #6]
ldmfd sp!, {r4 - r8, r10, r11, pc}

View file

@ -1,140 +1,140 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// bits.c
// This module provides utilities to support the BitStream structure which is
// used to read and write all WavPack audio data streams. It also contains a
// wrapper for the stream I/O functions and a set of functions dealing with
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
// the malloc() system is provided.
#include "wavpack.h"
#include <string.h>
#include <ctype.h>
////////////////////////// Bitstream functions ////////////////////////////////
// Open the specified BitStream and associate with the specified buffer.
static void bs_read (Bitstream *bs);
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes)
{
CLEAR (*bs);
bs->buf = buffer_start;
bs->end = buffer_end;
if (file) {
bs->ptr = bs->end - 1;
bs->file_bytes = file_bytes;
bs->file = file;
}
else
bs->ptr = bs->buf - 1;
bs->wrap = bs_read;
}
// This function is only called from the getbit() and getbits() macros when
// the BitStream has been exhausted and more data is required. Sinve these
// bistreams no longer access files, this function simple sets an error and
// resets the buffer.
static void bs_read (Bitstream *bs)
{
if (bs->file && bs->file_bytes) {
uint32_t bytes_read, bytes_to_read = bs->end - bs->buf;
if (bytes_to_read > bs->file_bytes)
bytes_to_read = bs->file_bytes;
bytes_read = bs->file (bs->buf, bytes_to_read);
if (bytes_read) {
bs->end = bs->buf + bytes_read;
bs->file_bytes -= bytes_read;
}
else {
memset (bs->buf, -1, bs->end - bs->buf);
bs->error = 1;
}
}
else
bs->error = 1;
if (bs->error)
memset (bs->buf, -1, bs->end - bs->buf);
bs->ptr = bs->buf;
}
/////////////////////// Endian Correction Routines ////////////////////////////
void little_endian_to_native (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
* (int32_t *) cp = temp;
cp += 4;
break;
case 'S':
temp = cp [0] + (cp [1] << 8);
* (short *) cp = (short) temp;
cp += 2;
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}
void native_to_little_endian (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = * (int32_t *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
*cp++ = (uchar) (temp >> 16);
*cp++ = (uchar) (temp >> 24);
break;
case 'S':
temp = * (short *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// bits.c
// This module provides utilities to support the BitStream structure which is
// used to read and write all WavPack audio data streams. It also contains a
// wrapper for the stream I/O functions and a set of functions dealing with
// endian-ness, both for enhancing portability. Finally, a debug wrapper for
// the malloc() system is provided.
#include "wavpack.h"
#include <string.h>
#include <ctype.h>
////////////////////////// Bitstream functions ////////////////////////////////
// Open the specified BitStream and associate with the specified buffer.
static void bs_read (Bitstream *bs);
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes)
{
CLEAR (*bs);
bs->buf = buffer_start;
bs->end = buffer_end;
if (file) {
bs->ptr = bs->end - 1;
bs->file_bytes = file_bytes;
bs->file = file;
}
else
bs->ptr = bs->buf - 1;
bs->wrap = bs_read;
}
// This function is only called from the getbit() and getbits() macros when
// the BitStream has been exhausted and more data is required. Sinve these
// bistreams no longer access files, this function simple sets an error and
// resets the buffer.
static void bs_read (Bitstream *bs)
{
if (bs->file && bs->file_bytes) {
uint32_t bytes_read, bytes_to_read = bs->end - bs->buf;
if (bytes_to_read > bs->file_bytes)
bytes_to_read = bs->file_bytes;
bytes_read = bs->file (bs->buf, bytes_to_read);
if (bytes_read) {
bs->end = bs->buf + bytes_read;
bs->file_bytes -= bytes_read;
}
else {
memset (bs->buf, -1, bs->end - bs->buf);
bs->error = 1;
}
}
else
bs->error = 1;
if (bs->error)
memset (bs->buf, -1, bs->end - bs->buf);
bs->ptr = bs->buf;
}
/////////////////////// Endian Correction Routines ////////////////////////////
void little_endian_to_native (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
* (int32_t *) cp = temp;
cp += 4;
break;
case 'S':
temp = cp [0] + (cp [1] << 8);
* (short *) cp = (short) temp;
cp += 2;
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}
void native_to_little_endian (void *data, char *format)
{
uchar *cp = (uchar *) data;
int32_t temp;
while (*format) {
switch (*format) {
case 'L':
temp = * (int32_t *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
*cp++ = (uchar) (temp >> 16);
*cp++ = (uchar) (temp >> 24);
break;
case 'S':
temp = * (short *) cp;
*cp++ = (uchar) temp;
*cp++ = (uchar) (temp >> 8);
break;
default:
if (isdigit (*format))
cp += *format - '0';
break;
}
format++;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,50 +1,50 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// float.c
#include "wavpack.h"
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
char *byteptr = wpmd->data;
if (bytecnt != 4)
return FALSE;
wps->float_flags = *byteptr++;
wps->float_shift = *byteptr++;
wps->float_max_exp = *byteptr++;
wps->float_norm_exp = *byteptr;
return TRUE;
}
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
{
int shift = wps->float_max_exp - wps->float_norm_exp + wps->float_shift;
if (shift > 32)
shift = 32;
else if (shift < -32)
shift = -32;
while (num_values--) {
if (shift > 0)
*values <<= shift;
else if (shift < 0)
*values >>= -shift;
if (*values > 8388607L)
*values = 8388607L;
else if (*values < -8388608L)
*values = -8388608L;
values++;
}
}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// float.c
#include "wavpack.h"
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
int bytecnt = wpmd->byte_length;
char *byteptr = wpmd->data;
if (bytecnt != 4)
return FALSE;
wps->float_flags = *byteptr++;
wps->float_shift = *byteptr++;
wps->float_max_exp = *byteptr++;
wps->float_norm_exp = *byteptr;
return TRUE;
}
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values)
{
int shift = wps->float_max_exp - wps->float_norm_exp + wps->float_shift;
if (shift > 32)
shift = 32;
else if (shift < -32)
shift = -32;
while (num_values--) {
if (shift > 0)
*values <<= shift;
else if (shift < 0)
*values >>= -shift;
if (*values > 8388607L)
*values = 8388607L;
else if (*values < -8388608L)
*values = -8388608L;
values++;
}
}

View file

@ -1,25 +1,25 @@
Copyright (c) 1998 - 2006 Conifer Software
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Conifer Software nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 1998 - 2006 Conifer Software
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Conifer Software nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,105 +1,105 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// metadata.c
// This module handles the metadata structure introduced in WavPack 4.0
#include "wavpack.h"
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd)
{
uchar tchar;
if (!wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length = tchar << 1;
if (wpmd->id & ID_LARGE) {
wpmd->id &= ~ID_LARGE;
if (!wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length += (int32_t) tchar << 9;
if (!wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length += (int32_t) tchar << 17;
}
if (wpmd->id & ID_ODD_SIZE) {
wpmd->id &= ~ID_ODD_SIZE;
wpmd->byte_length--;
}
if (wpmd->byte_length && wpmd->byte_length <= sizeof (wpc->read_buffer)) {
uint32_t bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1);
if (wpc->infile (wpc->read_buffer, bytes_to_read) != (int32_t) bytes_to_read) {
wpmd->data = NULL;
return FALSE;
}
wpmd->data = wpc->read_buffer;
}
else
wpmd->data = NULL;
return TRUE;
}
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
{
WavpackStream *wps = &wpc->stream;
switch (wpmd->id) {
case ID_DUMMY:
return TRUE;
case ID_DECORR_TERMS:
return read_decorr_terms (wps, wpmd);
case ID_DECORR_WEIGHTS:
return read_decorr_weights (wps, wpmd);
case ID_DECORR_SAMPLES:
return read_decorr_samples (wps, wpmd);
case ID_ENTROPY_VARS:
return read_entropy_vars (wps, wpmd);
case ID_HYBRID_PROFILE:
return read_hybrid_profile (wps, wpmd);
case ID_FLOAT_INFO:
return read_float_info (wps, wpmd);
case ID_INT32_INFO:
return read_int32_info (wps, wpmd);
case ID_CHANNEL_INFO:
return read_channel_info (wpc, wpmd);
case ID_CONFIG_BLOCK:
return read_config_info (wpc, wpmd);
case ID_WV_BITSTREAM:
return init_wv_bitstream (wpc, wpmd);
case ID_SHAPING_WEIGHTS:
case ID_WVC_BITSTREAM:
case ID_WVX_BITSTREAM:
return TRUE;
default:
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
}
}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// metadata.c
// This module handles the metadata structure introduced in WavPack 4.0
#include "wavpack.h"
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd)
{
uchar tchar;
if (!wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length = tchar << 1;
if (wpmd->id & ID_LARGE) {
wpmd->id &= ~ID_LARGE;
if (!wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length += (int32_t) tchar << 9;
if (!wpc->infile (&tchar, 1))
return FALSE;
wpmd->byte_length += (int32_t) tchar << 17;
}
if (wpmd->id & ID_ODD_SIZE) {
wpmd->id &= ~ID_ODD_SIZE;
wpmd->byte_length--;
}
if (wpmd->byte_length && wpmd->byte_length <= sizeof (wpc->read_buffer)) {
uint32_t bytes_to_read = wpmd->byte_length + (wpmd->byte_length & 1);
if (wpc->infile (wpc->read_buffer, bytes_to_read) != (int32_t) bytes_to_read) {
wpmd->data = NULL;
return FALSE;
}
wpmd->data = wpc->read_buffer;
}
else
wpmd->data = NULL;
return TRUE;
}
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
{
WavpackStream *wps = &wpc->stream;
switch (wpmd->id) {
case ID_DUMMY:
return TRUE;
case ID_DECORR_TERMS:
return read_decorr_terms (wps, wpmd);
case ID_DECORR_WEIGHTS:
return read_decorr_weights (wps, wpmd);
case ID_DECORR_SAMPLES:
return read_decorr_samples (wps, wpmd);
case ID_ENTROPY_VARS:
return read_entropy_vars (wps, wpmd);
case ID_HYBRID_PROFILE:
return read_hybrid_profile (wps, wpmd);
case ID_FLOAT_INFO:
return read_float_info (wps, wpmd);
case ID_INT32_INFO:
return read_int32_info (wps, wpmd);
case ID_CHANNEL_INFO:
return read_channel_info (wpc, wpmd);
case ID_CONFIG_BLOCK:
return read_config_info (wpc, wpmd);
case ID_WV_BITSTREAM:
return init_wv_bitstream (wpc, wpmd);
case ID_SHAPING_WEIGHTS:
case ID_WVC_BITSTREAM:
case ID_WVX_BITSTREAM:
return TRUE;
default:
return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
}
}

View file

@ -1,68 +1,68 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
This package contains a tiny version of the WavPack 4.40 decoder that might
be used in a "resource limited" CPU environment or form the basis for a
hardware decoding implementation. It is packaged with a demo command-line
program that accepts a WavPack audio file on stdin and outputs a RIFF wav
file to stdout. The program is standard C, and a win32 executable is
included which was compiled under MS Visual C++ 6.0 using this command:
cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c
WavPack data is read with a stream reading callback. No direct seeking is
provided for, but it is possible to start decoding anywhere in a WavPack
stream. In this case, WavPack will be able to provide the sample-accurate
position when it synchs with the data and begins decoding. The WIN32 macro
is used for Windows to force the stdin and stdout streams to be binary mode.
Compared to the previous version, this library has been optimized somewhat
for improved performance in exchange for slightly larger code size. The
library also now includes hand-optimized assembly language versions of the
decorrelation functions for both the ColdFire (w/EMAC) and ARM processors.
For demonstration purposes this uses a single static copy of the
WavpackContext structure, so obviously it cannot be used for more than one
file at a time. Also, this decoder will not handle "correction" files, plays
only the first two channels of multi-channel files, and is limited in
resolution in some large integer or floating point files (but always
provides at least 24 bits of resolution). It also will not accept WavPack
files from before version 4.0.
The previous version of this library would handle float files by returning
32-bit floating-point data (even though no floating point math was used).
Because this library would normally be used for simply playing WavPack
files where lossless performance (beyond 24-bits) is not relevant, I have
changed this behavior. Now, these files will generate clipped 24-bit data.
The MODE_FLOAT flag will still be returned by WavpackGetMode(), but the
BitsPerSample and BytesPerSample queries will be 24 and 3, respectfully.
What this means is that an application that can handle 24-bit data will
now be able to handle floating point data (assuming that the MODE_FLOAT
flag is ignored).
To make this code viable on the greatest number of hardware platforms, the
following are true:
speed is about 5x realtime on an AMD K6 300 MHz
("high" mode 16/44 stereo; normal mode is about twice that fast)
no floating-point math required; just 32b * 32b = 32b int multiply
large data areas are static and less than 4K total
executable code and tables are less than 40K
no malloc / free usage
To maintain compatibility on various platforms, the following conventions
are used:
a "char" must be exactly 8-bits
a "short" must be exactly 16-bits
an "int" must be at least 16-bits, but may be larger
the "long" type is not used to avoid problems with 64-bit compilers
Questions or comments should be directed to david@wavpack.com
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
This package contains a tiny version of the WavPack 4.40 decoder that might
be used in a "resource limited" CPU environment or form the basis for a
hardware decoding implementation. It is packaged with a demo command-line
program that accepts a WavPack audio file on stdin and outputs a RIFF wav
file to stdout. The program is standard C, and a win32 executable is
included which was compiled under MS Visual C++ 6.0 using this command:
cl /O1 /DWIN32 wvfilter.c wputils.c unpack.c float.c metadata.c words.c bits.c
WavPack data is read with a stream reading callback. No direct seeking is
provided for, but it is possible to start decoding anywhere in a WavPack
stream. In this case, WavPack will be able to provide the sample-accurate
position when it synchs with the data and begins decoding. The WIN32 macro
is used for Windows to force the stdin and stdout streams to be binary mode.
Compared to the previous version, this library has been optimized somewhat
for improved performance in exchange for slightly larger code size. The
library also now includes hand-optimized assembly language versions of the
decorrelation functions for both the ColdFire (w/EMAC) and ARM processors.
For demonstration purposes this uses a single static copy of the
WavpackContext structure, so obviously it cannot be used for more than one
file at a time. Also, this decoder will not handle "correction" files, plays
only the first two channels of multi-channel files, and is limited in
resolution in some large integer or floating point files (but always
provides at least 24 bits of resolution). It also will not accept WavPack
files from before version 4.0.
The previous version of this library would handle float files by returning
32-bit floating-point data (even though no floating point math was used).
Because this library would normally be used for simply playing WavPack
files where lossless performance (beyond 24-bits) is not relevant, I have
changed this behavior. Now, these files will generate clipped 24-bit data.
The MODE_FLOAT flag will still be returned by WavpackGetMode(), but the
BitsPerSample and BytesPerSample queries will be 24 and 3, respectfully.
What this means is that an application that can handle 24-bit data will
now be able to handle floating point data (assuming that the MODE_FLOAT
flag is ignored).
To make this code viable on the greatest number of hardware platforms, the
following are true:
speed is about 5x realtime on an AMD K6 300 MHz
("high" mode 16/44 stereo; normal mode is about twice that fast)
no floating-point math required; just 32b * 32b = 32b int multiply
large data areas are static and less than 4K total
executable code and tables are less than 40K
no malloc / free usage
To maintain compatibility on various platforms, the following conventions
are used:
a "char" must be exactly 8-bits
a "short" must be exactly 16-bits
an "int" must be at least 16-bits, but may be larger
the "long" type is not used to avoid problems with 64-bit compilers
Questions or comments should be directed to david@wavpack.com

File diff suppressed because it is too large Load diff

View file

@ -5,56 +5,56 @@
/* All Rights Reserved. // */
/* Distributed under the BSD Software License (see license.txt) // */
/*////////////////////////////////////////////////////////////////////////// */
/* wavpack.h */
#include <sys/types.h>
#include <sys/types.h>
/* This header file contains all the definitions required by WavPack. */
#ifdef __BORLANDC__
typedef unsigned long uint32_t;
typedef long int32_t;
#elif defined(_WIN32) && !defined(__MINGW32__)
#include <stdlib.h>
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
#else
#include <inttypes.h>
#endif
typedef unsigned char uchar;
#if !defined(__GNUC__) || defined(WIN32)
typedef unsigned short ushort;
typedef unsigned int uint;
#endif
#include <stdio.h>
#define FALSE 0
#define TRUE 1
#ifdef __BORLANDC__
typedef unsigned long uint32_t;
typedef long int32_t;
#elif defined(_WIN32) && !defined(__MINGW32__)
#include <stdlib.h>
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
#else
#include <inttypes.h>
#endif
typedef unsigned char uchar;
#if !defined(__GNUC__) || defined(WIN32)
typedef unsigned short ushort;
typedef unsigned int uint;
#endif
#include <stdio.h>
#define FALSE 0
#define TRUE 1
/*//////////////////////////// WavPack Header ///////////////////////////////// */
/* Note that this is the ONLY structure that is written to (or read from) */
/* WavPack 4.0 files, and is the preamble to every block in both the .wv */
/* and .wvc files. */
typedef struct {
char ckID [4];
uint32_t ckSize;
short version;
uchar track_no, index_no;
uint32_t total_samples, block_index, block_samples, flags, crc;
} WavpackHeader;
#define WavpackHeaderFormat "4LS2LLLLL"
typedef struct {
char ckID [4];
uint32_t ckSize;
short version;
uchar track_no, index_no;
uint32_t total_samples, block_index, block_samples, flags, crc;
} WavpackHeader;
#define WavpackHeaderFormat "4LS2LLLLL"
/* or-values for "flags" */
#define BYTES_STORED 3 /* 1-4 bytes/sample */
#define MONO_FLAG 4 /* not stereo */
#define HYBRID_FLAG 8 /* hybrid mode */
@ -62,83 +62,83 @@ typedef struct {
#define CROSS_DECORR 0x20 /* no-delay cross decorrelation */
#define HYBRID_SHAPE 0x40 /* noise shape (hybrid mode only) */
#define FLOAT_DATA 0x80 /* ieee 32-bit floating point data */
#define INT32_DATA 0x100 /* special extended int handling */
#define HYBRID_BITRATE 0x200 /* bitrate noise (hybrid mode only) */
#define HYBRID_BALANCE 0x400 /* balance noise (hybrid stereo mode only) */
#define INITIAL_BLOCK 0x800 /* initial block of multichannel segment */
#define FINAL_BLOCK 0x1000 /* final block of multichannel segment */
#define SHIFT_LSB 13
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
#define MAG_LSB 18
#define MAG_MASK (0x1fL << MAG_LSB)
#define SRATE_LSB 23
#define SRATE_MASK (0xfL << SRATE_LSB)
#define SHIFT_LSB 13
#define SHIFT_MASK (0x1fL << SHIFT_LSB)
#define MAG_LSB 18
#define MAG_MASK (0x1fL << MAG_LSB)
#define SRATE_LSB 23
#define SRATE_MASK (0xfL << SRATE_LSB)
#define FALSE_STEREO 0x40000000 /* block is stereo, but data is mono */
#define IGNORED_FLAGS 0x18000000 /* reserved, but ignore if encountered */
#define NEW_SHAPING 0x20000000 /* use IIR filter for negative shaping */
#define UNKNOWN_FLAGS 0x80000000 /* also reserved, but refuse decode if */
/* encountered */
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
#define MONO_DATA (MONO_FLAG | FALSE_STEREO)
#define MIN_STREAM_VERS 0x402 /* lowest stream version we'll decode */
#define MAX_STREAM_VERS 0x410 /* highest stream version we'll decode */
/*////////////////////////// WavPack Metadata ///////////////////////////////// */
/* This is an internal representation of metadata. */
typedef struct {
int32_t byte_length;
void *data;
uchar id;
} WavpackMetadata;
#define ID_OPTIONAL_DATA 0x20
#define ID_ODD_SIZE 0x40
#define ID_LARGE 0x80
#define ID_DUMMY 0x0
#define ID_ENCODER_INFO 0x1
#define ID_DECORR_TERMS 0x2
#define ID_DECORR_WEIGHTS 0x3
#define ID_DECORR_SAMPLES 0x4
#define ID_ENTROPY_VARS 0x5
#define ID_HYBRID_PROFILE 0x6
#define ID_SHAPING_WEIGHTS 0x7
#define ID_FLOAT_INFO 0x8
#define ID_INT32_INFO 0x9
#define ID_WV_BITSTREAM 0xa
#define ID_WVC_BITSTREAM 0xb
#define ID_WVX_BITSTREAM 0xc
#define ID_CHANNEL_INFO 0xd
#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3)
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
typedef struct {
int32_t byte_length;
void *data;
uchar id;
} WavpackMetadata;
#define ID_OPTIONAL_DATA 0x20
#define ID_ODD_SIZE 0x40
#define ID_LARGE 0x80
#define ID_DUMMY 0x0
#define ID_ENCODER_INFO 0x1
#define ID_DECORR_TERMS 0x2
#define ID_DECORR_WEIGHTS 0x3
#define ID_DECORR_SAMPLES 0x4
#define ID_ENTROPY_VARS 0x5
#define ID_HYBRID_PROFILE 0x6
#define ID_SHAPING_WEIGHTS 0x7
#define ID_FLOAT_INFO 0x8
#define ID_INT32_INFO 0x9
#define ID_WV_BITSTREAM 0xa
#define ID_WVC_BITSTREAM 0xb
#define ID_WVX_BITSTREAM 0xc
#define ID_CHANNEL_INFO 0xd
#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1)
#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2)
#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3)
#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4)
#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5)
#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6)
/*/////////////////////// WavPack Configuration /////////////////////////////// */
/* This internal structure is used during encode to provide configuration to */
/* the encoding engine and during decoding to provide fle information back to */
/* the higher level functions. Not all fields are used in both modes. */
typedef struct {
int bits_per_sample, bytes_per_sample;
int num_channels, float_norm_exp;
uint32_t flags, sample_rate, channel_mask;
} WavpackConfig;
typedef struct {
int bits_per_sample, bytes_per_sample;
int num_channels, float_norm_exp;
uint32_t flags, sample_rate, channel_mask;
} WavpackConfig;
#define CONFIG_BYTES_STORED 3 /* 1-4 bytes/sample */
#define CONFIG_MONO_FLAG 4 /* not stereo */
#define CONFIG_HYBRID_FLAG 8 /* hybrid mode */
@ -146,7 +146,7 @@ typedef struct {
#define CONFIG_CROSS_DECORR 0x20 /* no-delay cross decorrelation */
#define CONFIG_HYBRID_SHAPE 0x40 /* noise shape (hybrid mode only) */
#define CONFIG_FLOAT_DATA 0x80 /* ieee 32-bit floating point data */
#define CONFIG_FAST_FLAG 0x200 /* fast mode */
#define CONFIG_HIGH_FLAG 0x800 /* high quality mode */
#define CONFIG_VERY_HIGH_FLAG 0x1000 /* very high */
@ -163,127 +163,127 @@ typedef struct {
#define CONFIG_SKIP_WVX 0x4000000 /* no wvx stream w/ floats & big ints */
#define CONFIG_MD5_CHECKSUM 0x8000000 /* compute & store MD5 signature */
#define CONFIG_OPTIMIZE_MONO 0x80000000 /* optimize for mono streams posing as stereo */
/*////////////////////////////// WavPack Stream /////////////////////////////// */
/* This internal structure contains everything required to handle a WavPack */
/* "stream", which is defined as a stereo or mono stream of audio samples. For */
/* multichannel audio several of these would be required. Each stream contains */
/* pointers to hold a complete allocated block of WavPack data, although it's */
/* possible to decode WavPack blocks without buffering an entire block. */
typedef int32_t (*read_stream)(void *, int32_t);
typedef struct bs {
uchar *buf, *end, *ptr;
void (*wrap)(struct bs *bs);
uint32_t file_bytes, sr;
int error, bc;
read_stream file;
} Bitstream;
#define MAX_NTERMS 16
#define MAX_TERM 8
struct decorr_pass {
short term, delta, weight_A, weight_B;
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
};
struct entropy_data {
uint32_t median [3], slow_level, error_limit;
};
struct words_data {
uint32_t bitrate_delta [2], bitrate_acc [2];
uint32_t pend_data, holding_one, zeros_acc;
int holding_zero, pend_count;
struct entropy_data c [2];
};
typedef struct {
WavpackHeader wphdr;
Bitstream wvbits;
struct words_data w;
int num_terms, mute_error;
uint32_t sample_index, crc;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
struct decorr_pass decorr_passes [MAX_NTERMS];
} WavpackStream;
typedef int32_t (*read_stream)(void *, int32_t);
typedef struct bs {
uchar *buf, *end, *ptr;
void (*wrap)(struct bs *bs);
uint32_t file_bytes, sr;
int error, bc;
read_stream file;
} Bitstream;
#define MAX_NTERMS 16
#define MAX_TERM 8
struct decorr_pass {
short term, delta, weight_A, weight_B;
int32_t samples_A [MAX_TERM], samples_B [MAX_TERM];
};
struct entropy_data {
uint32_t median [3], slow_level, error_limit;
};
struct words_data {
uint32_t bitrate_delta [2], bitrate_acc [2];
uint32_t pend_data, holding_one, zeros_acc;
int holding_zero, pend_count;
struct entropy_data c [2];
};
typedef struct {
WavpackHeader wphdr;
Bitstream wvbits;
struct words_data w;
int num_terms, mute_error;
uint32_t sample_index, crc;
uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups;
uchar float_flags, float_shift, float_max_exp, float_norm_exp;
struct decorr_pass decorr_passes [MAX_NTERMS];
} WavpackStream;
/* flags for float_flags: */
#define FLOAT_SHIFT_ONES 1 /* bits left-shifted into float = '1' */
#define FLOAT_SHIFT_SAME 2 /* bits left-shifted into float are the same */
#define FLOAT_SHIFT_SENT 4 /* bits shifted into float are sent literally */
#define FLOAT_ZEROS_SENT 8 /* "zeros" are not all real zeros */
#define FLOAT_NEG_ZEROS 0x10 /* contains negative zeros */
#define FLOAT_EXCEPTIONS 0x20 /* contains exceptions (inf, nan, etc.) */
/*///////////////////////////// WavPack Context /////////////////////////////// */
/* This internal structure holds everything required to encode or decode WavPack */
/* files. It is recommended that direct access to this structure be minimized */
/* and the provided utilities used instead. */
typedef struct {
WavpackConfig config;
WavpackStream stream;
uchar read_buffer [1024];
char error_message [80];
read_stream infile;
uint32_t total_samples, crc_errors, first_flags;
int open_flags, norm_offset, reduced_channels, lossy_blocks;
} WavpackContext;
typedef struct {
WavpackConfig config;
WavpackStream stream;
uchar read_buffer [1024];
char error_message [80];
read_stream infile;
uint32_t total_samples, crc_errors, first_flags;
int open_flags, norm_offset, reduced_channels, lossy_blocks;
} WavpackContext;
/*////////////////////// function prototypes and macros ////////////////////// */
#define CLEAR(destin) memset (&destin, 0, sizeof (destin));
#define CLEAR(destin) memset (&destin, 0, sizeof (destin));
/* bits.c */
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes);
#define bs_is_open(bs) ((bs)->ptr != NULL)
#define getbit(bs) ( \
(((bs)->bc) ? \
((bs)->bc--, (bs)->sr & 1) : \
(((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \
) ? \
((bs)->sr >>= 1, 1) : \
((bs)->sr >>= 1, 0) \
)
#define getbits(value, nbits, bs) { \
while ((nbits) > (bs)->bc) { \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
(bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \
(bs)->bc += 8; \
} \
*(value) = (bs)->sr; \
if ((bs)->bc > 32) { \
(bs)->bc -= (nbits); \
(bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \
} \
else { \
(bs)->bc -= (nbits); \
(bs)->sr >>= (nbits); \
} \
}
void little_endian_to_native (void *data, char *format);
void native_to_little_endian (void *data, char *format);
void bs_open_read (Bitstream *bs, uchar *buffer_start, uchar *buffer_end, read_stream file, uint32_t file_bytes);
#define bs_is_open(bs) ((bs)->ptr != NULL)
#define getbit(bs) ( \
(((bs)->bc) ? \
((bs)->bc--, (bs)->sr & 1) : \
(((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = 7, ((bs)->sr = *((bs)->ptr)) & 1) \
) ? \
((bs)->sr >>= 1, 1) : \
((bs)->sr >>= 1, 0) \
)
#define getbits(value, nbits, bs) { \
while ((nbits) > (bs)->bc) { \
if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \
(bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \
(bs)->bc += 8; \
} \
*(value) = (bs)->sr; \
if ((bs)->bc > 32) { \
(bs)->bc -= (nbits); \
(bs)->sr = *((bs)->ptr) >> (8 - (bs)->bc); \
} \
else { \
(bs)->bc -= (nbits); \
(bs)->sr >>= (nbits); \
} \
}
void little_endian_to_native (void *data, char *format);
void native_to_little_endian (void *data, char *format);
/* These macros implement the weight application and update operations */
/* that are at the heart of the decorrelation loops. Note that when there */
/* are several alternative versions of the same macro (marked with PERFCOND) */
@ -291,94 +291,94 @@ void native_to_little_endian (void *data, char *format);
/* decoding and the user should choose the one that provides the best */
/* performance. This may be easier to check when NOT using the assembly */
/* language optimizations. */
#if 1 /* PERFCOND */
#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
#else
#define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2)
#endif
#define apply_weight_f(weight, sample) (((((sample & 0xffffL) * weight) >> 9) + \
(((sample & ~0xffffL) >> 9) * weight) + 1) >> 1)
#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10)
#else
#define apply_weight_i(weight, sample) ((((weight * sample) >> 8) + 2) >> 2)
#endif
#define apply_weight_f(weight, sample) (((((sample & 0xffffL) * weight) >> 9) + \
(((sample & ~0xffffL) >> 9) * weight) + 1) >> 1)
#if 1 /* PERFCOND */
#define apply_weight(weight, sample) (sample != (short) sample ? \
apply_weight_f (weight, sample) : apply_weight_i (weight, sample))
#else
#define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10))
#endif
#define apply_weight(weight, sample) (sample != (short) sample ? \
apply_weight_f (weight, sample) : apply_weight_i (weight, sample))
#else
#define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10))
#endif
#if 0 /* PERFCOND */
#define update_weight(weight, delta, source, result) \
if (source && result) { int32_t s = (int32_t) (source ^ result) >> 31; weight = (delta ^ s) + (weight - s); }
#elif 1
#define update_weight(weight, delta, source, result) \
if (source && result) weight += (((source ^ result) >> 30) | 1) * delta
#else
#define update_weight(weight, delta, source, result) \
if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta)
#endif
#define update_weight_clip(weight, delta, source, result) \
if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
weight = weight < 0 ? -1024 : 1024
#define update_weight(weight, delta, source, result) \
if (source && result) { int32_t s = (int32_t) (source ^ result) >> 31; weight = (delta ^ s) + (weight - s); }
#elif 1
#define update_weight(weight, delta, source, result) \
if (source && result) weight += (((source ^ result) >> 30) | 1) * delta
#else
#define update_weight(weight, delta, source, result) \
if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta)
#endif
#define update_weight_clip(weight, delta, source, result) \
if (source && result && ((source ^ result) < 0 ? (weight -= delta) < -1024 : (weight += delta) > 1024)) \
weight = weight < 0 ? -1024 : 1024
/* unpack.c */
int unpack_init (WavpackContext *wpc);
int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd);
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
int check_crc_error (WavpackContext *wpc);
int unpack_init (WavpackContext *wpc);
int init_wv_bitstream (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd);
int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd);
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd);
int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd);
int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count);
int check_crc_error (WavpackContext *wpc);
/* metadata.c stuff */
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd);
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd);
int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
/* words.c stuff */
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
int32_t get_words (int32_t *buffer, int nsamples, uint32_t flags,
struct words_data *w, Bitstream *bs);
int32_t exp2s (int log);
int restore_weight (signed char weight);
#define WORD_EOF (1L << 31)
int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd);
int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd);
int32_t get_words (int32_t *buffer, int nsamples, uint32_t flags,
struct words_data *w, Bitstream *bs);
int32_t exp2s (int log);
int restore_weight (signed char weight);
#define WORD_EOF (1L << 31)
/* float.c */
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values);
int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd);
void float_values (WavpackStream *wps, int32_t *values, int32_t num_values);
/* wputils.c */
WavpackContext *WavpackOpenFileInput (read_stream infile, char *error);
int WavpackGetMode (WavpackContext *wpc);
#define MODE_WVC 0x1
#define MODE_LOSSLESS 0x2
#define MODE_HYBRID 0x4
#define MODE_FLOAT 0x8
#define MODE_VALID_TAG 0x10
#define MODE_HIGH 0x20
#define MODE_FAST 0x40
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
int WavpackGetNumErrors (WavpackContext *wpc);
int WavpackLossyBlocks (WavpackContext *wpc);
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);
WavpackContext *WavpackOpenFileInput (read_stream infile, char *error);
int WavpackGetMode (WavpackContext *wpc);
#define MODE_WVC 0x1
#define MODE_LOSSLESS 0x2
#define MODE_HYBRID 0x4
#define MODE_FLOAT 0x8
#define MODE_VALID_TAG 0x10
#define MODE_HIGH 0x20
#define MODE_FAST 0x40
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples);
uint32_t WavpackGetNumSamples (WavpackContext *wpc);
uint32_t WavpackGetSampleIndex (WavpackContext *wpc);
int WavpackGetNumErrors (WavpackContext *wpc);
int WavpackLossyBlocks (WavpackContext *wpc);
uint32_t WavpackGetSampleRate (WavpackContext *wpc);
int WavpackGetBitsPerSample (WavpackContext *wpc);
int WavpackGetBytesPerSample (WavpackContext *wpc);
int WavpackGetNumChannels (WavpackContext *wpc);
int WavpackGetReducedChannels (WavpackContext *wpc);

File diff suppressed because it is too large Load diff

View file

@ -1,351 +1,351 @@
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wputils.c
// This module provides a high-level interface for decoding WavPack 4.0 audio
// streams and files. WavPack data is read with a stream reading callback. No
// direct seeking is provided for, but it is possible to start decoding
// anywhere in a WavPack stream. In this case, WavPack will be able to provide
// the sample-accurate position when it synchs with the data and begins
// decoding.
#include "wavpack.h"
#include <string.h>
///////////////////////////// local table storage ////////////////////////////
const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
///////////////////////////// executable code ////////////////////////////////
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr);
// This function reads data from the specified stream in search of a valid
// WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
// unsupported WavPack block is encountered) then an appropriate message is
// copied to "error" and NULL is returned, otherwise a pointer to a
// WavpackContext structure is returned (which is used to call all other
// functions in this module). This can be initiated at the beginning of a
// WavPack file, or anywhere inside a WavPack file. To determine the exact
// position within the file use WavpackGetSampleIndex(). For demonstration
// purposes this uses a single static copy of the WavpackContext structure,
// so obviously it cannot be used for more than one file at a time. Also,
// this function will not handle "correction" files, plays only the first
// two channels of multi-channel files, and is limited in resolution in some
// large integer or floating point files (but always provides at least 24 bits
// of resolution).
static WavpackContext wpc;
WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
{
WavpackStream *wps = &wpc.stream;
uint32_t bcount;
CLEAR (wpc);
wpc.infile = infile;
wpc.total_samples = (uint32_t) -1;
wpc.norm_offset = 0;
wpc.open_flags = 0;
// open the source file for reading and store the size
while (!wps->wphdr.block_samples) {
bcount = read_next_header (wpc.infile, &wps->wphdr);
if (bcount == (uint32_t) -1) {
strcpy (error, "not compatible with this version of WavPack file!");
return NULL;
}
if (wps->wphdr.block_samples && wps->wphdr.total_samples != (uint32_t) -1)
wpc.total_samples = wps->wphdr.total_samples;
if (!unpack_init (&wpc)) {
strcpy (error, wpc.error_message [0] ? wpc.error_message :
"not compatible with this version of WavPack file!");
return NULL;
}
}
wpc.config.flags &= ~0xff;
wpc.config.flags |= wps->wphdr.flags & 0xff;
wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
wpc.config.float_norm_exp = wps->float_norm_exp;
wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) -
((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
if (wpc.config.flags & FLOAT_DATA) {
wpc.config.bytes_per_sample = 3;
wpc.config.bits_per_sample = 24;
}
if (!wpc.config.sample_rate) {
if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
wpc.config.sample_rate = 44100;
else
wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
}
if (!wpc.config.num_channels) {
wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
}
if (!(wps->wphdr.flags & FINAL_BLOCK))
wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
return &wpc;
}
// This function obtains general information about an open file and returns
// a mask with the following bit values:
// MODE_LOSSLESS: file is lossless (pure lossless only)
// MODE_HYBRID: file is hybrid mode (lossy part only)
// MODE_FLOAT: audio data is 32-bit ieee floating point (but will provided
// in 24-bit integers for convenience)
// MODE_HIGH: file was created in "high" mode (information only)
// MODE_FAST: file was created in "fast" mode (information only)
int WavpackGetMode (WavpackContext *wpc)
{
int mode = 0;
if (wpc) {
if (wpc->config.flags & CONFIG_HYBRID_FLAG)
mode |= MODE_HYBRID;
else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
mode |= MODE_LOSSLESS;
if (wpc->lossy_blocks)
mode &= ~MODE_LOSSLESS;
if (wpc->config.flags & CONFIG_FLOAT_DATA)
mode |= MODE_FLOAT;
if (wpc->config.flags & CONFIG_HIGH_FLAG)
mode |= MODE_HIGH;
if (wpc->config.flags & CONFIG_FAST_FLAG)
mode |= MODE_FAST;
}
return mode;
}
// Unpack the specified number of samples from the current file position.
// Note that "samples" here refers to "complete" samples, which would be
// 2 longs for stereo files. The audio data is returned right-justified in
// 32-bit longs in the endian mode native to the executing processor. So,
// if the original data was 16-bit, then the values returned would be
// +/-32k. Floating point data will be returned as 24-bit integers (and may
// also be clipped). The actual number of samples unpacked is returned,
// which should be equal to the number requested unless the end of fle is
// encountered or an error occurs.
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples)
{
WavpackStream *wps = &wpc->stream;
uint32_t bcount, samples_unpacked = 0, samples_to_unpack;
int num_channels = wpc->config.num_channels;
while (samples) {
if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
bcount = read_next_header (wpc->infile, &wps->wphdr);
if (bcount == (uint32_t) -1)
break;
if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
if (!unpack_init (wpc))
break;
}
if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
continue;
if (wps->sample_index < wps->wphdr.block_index) {
samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
if (samples_to_unpack > samples)
samples_to_unpack = samples;
wps->sample_index += samples_to_unpack;
samples_unpacked += samples_to_unpack;
samples -= samples_to_unpack;
if (wpc->reduced_channels)
samples_to_unpack *= wpc->reduced_channels;
else
samples_to_unpack *= num_channels;
while (samples_to_unpack--)
*buffer++ = 0;
continue;
}
samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
if (samples_to_unpack > samples)
samples_to_unpack = samples;
unpack_samples (wpc, buffer, samples_to_unpack);
if (wpc->reduced_channels)
buffer += samples_to_unpack * wpc->reduced_channels;
else
buffer += samples_to_unpack * num_channels;
samples_unpacked += samples_to_unpack;
samples -= samples_to_unpack;
if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
if (check_crc_error (wpc))
wpc->crc_errors++;
}
if (wps->sample_index == wpc->total_samples)
break;
}
return samples_unpacked;
}
// Get total number of samples contained in the WavPack file, or -1 if unknown
uint32_t WavpackGetNumSamples (WavpackContext *wpc)
{
return wpc ? wpc->total_samples : (uint32_t) -1;
}
// Get the current sample index position, or -1 if unknown
uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
{
if (wpc)
return wpc->stream.sample_index;
return (uint32_t) -1;
}
// Get the number of errors encountered so far
int WavpackGetNumErrors (WavpackContext *wpc)
{
return wpc ? wpc->crc_errors : 0;
}
// return TRUE if any uncorrected lossy blocks were actually written or read
int WavpackLossyBlocks (WavpackContext *wpc)
{
return wpc ? wpc->lossy_blocks : 0;
}
// Returns the sample rate of the specified WavPack file
uint32_t WavpackGetSampleRate (WavpackContext *wpc)
{
return wpc ? wpc->config.sample_rate : 44100;
}
// Returns the number of channels of the specified WavPack file. Note that
// this is the actual number of channels contained in the file, but this
// version can only decode the first two.
int WavpackGetNumChannels (WavpackContext *wpc)
{
return wpc ? wpc->config.num_channels : 2;
}
// Returns the actual number of valid bits per sample contained in the
// original file, which may or may not be a multiple of 8. Floating data
// always has 32 bits, integers may be from 1 to 32 bits each. When this
// value is not a multiple of 8, then the "extra" bits are located in the
// LSBs of the results. That is, values are right justified when unpacked
// into longs, but are left justified in the number of bytes used by the
// original data.
int WavpackGetBitsPerSample (WavpackContext *wpc)
{
return wpc ? wpc->config.bits_per_sample : 16;
}
// Returns the number of bytes used for each sample (1 to 4) in the original
// file. This is required information for the user of this module because the
// audio data is returned in the LOWER bytes of the long buffer and must be
// left-shifted 8, 16, or 24 bits if normalized longs are required.
int WavpackGetBytesPerSample (WavpackContext *wpc)
{
return wpc ? wpc->config.bytes_per_sample : 2;
}
// This function will return the actual number of channels decoded from the
// file (which may or may not be less than the actual number of channels, but
// will always be 1 or 2). Normally, this will be the front left and right
// channels of a multi-channel file.
int WavpackGetReducedChannels (WavpackContext *wpc)
{
if (wpc)
return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
else
return 2;
}
// Read from current file position until a valid 32-byte WavPack 4.0 header is
// found and read into the specified pointer. The number of bytes skipped is
// returned. If no WavPack header is found within 1 meg, then a -1 is returned
// to indicate the error. No additional bytes are read past the header and it
// is returned in the processor's native endian mode. Seeking is not required.
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr)
{
char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
uint32_t bytes_skipped = 0;
int bleft;
while (1) {
if (sp < ep) {
bleft = ep - sp;
memcpy (buffer, sp, bleft);
}
else
bleft = 0;
if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (int32_t) sizeof (*wphdr) - bleft)
return -1;
sp = buffer;
if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
!(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 &&
sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff)) {
memcpy (wphdr, buffer, sizeof (*wphdr));
little_endian_to_native (wphdr, WavpackHeaderFormat);
return bytes_skipped;
}
while (sp < ep && *sp != 'w')
sp++;
if ((bytes_skipped += sp - buffer) > 1048576L)
return -1;
}
}
////////////////////////////////////////////////////////////////////////////
// **** WAVPACK **** //
// Hybrid Lossless Wavefile Compressor //
// Copyright (c) 1998 - 2006 Conifer Software. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// wputils.c
// This module provides a high-level interface for decoding WavPack 4.0 audio
// streams and files. WavPack data is read with a stream reading callback. No
// direct seeking is provided for, but it is possible to start decoding
// anywhere in a WavPack stream. In this case, WavPack will be able to provide
// the sample-accurate position when it synchs with the data and begins
// decoding.
#include "wavpack.h"
#include <string.h>
///////////////////////////// local table storage ////////////////////////////
const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
///////////////////////////// executable code ////////////////////////////////
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr);
// This function reads data from the specified stream in search of a valid
// WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
// unsupported WavPack block is encountered) then an appropriate message is
// copied to "error" and NULL is returned, otherwise a pointer to a
// WavpackContext structure is returned (which is used to call all other
// functions in this module). This can be initiated at the beginning of a
// WavPack file, or anywhere inside a WavPack file. To determine the exact
// position within the file use WavpackGetSampleIndex(). For demonstration
// purposes this uses a single static copy of the WavpackContext structure,
// so obviously it cannot be used for more than one file at a time. Also,
// this function will not handle "correction" files, plays only the first
// two channels of multi-channel files, and is limited in resolution in some
// large integer or floating point files (but always provides at least 24 bits
// of resolution).
static WavpackContext wpc;
WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
{
WavpackStream *wps = &wpc.stream;
uint32_t bcount;
CLEAR (wpc);
wpc.infile = infile;
wpc.total_samples = (uint32_t) -1;
wpc.norm_offset = 0;
wpc.open_flags = 0;
// open the source file for reading and store the size
while (!wps->wphdr.block_samples) {
bcount = read_next_header (wpc.infile, &wps->wphdr);
if (bcount == (uint32_t) -1) {
strcpy (error, "not compatible with this version of WavPack file!");
return NULL;
}
if (wps->wphdr.block_samples && wps->wphdr.total_samples != (uint32_t) -1)
wpc.total_samples = wps->wphdr.total_samples;
if (!unpack_init (&wpc)) {
strcpy (error, wpc.error_message [0] ? wpc.error_message :
"not compatible with this version of WavPack file!");
return NULL;
}
}
wpc.config.flags &= ~0xff;
wpc.config.flags |= wps->wphdr.flags & 0xff;
wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
wpc.config.float_norm_exp = wps->float_norm_exp;
wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) -
((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
if (wpc.config.flags & FLOAT_DATA) {
wpc.config.bytes_per_sample = 3;
wpc.config.bits_per_sample = 24;
}
if (!wpc.config.sample_rate) {
if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
wpc.config.sample_rate = 44100;
else
wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
}
if (!wpc.config.num_channels) {
wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
}
if (!(wps->wphdr.flags & FINAL_BLOCK))
wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
return &wpc;
}
// This function obtains general information about an open file and returns
// a mask with the following bit values:
// MODE_LOSSLESS: file is lossless (pure lossless only)
// MODE_HYBRID: file is hybrid mode (lossy part only)
// MODE_FLOAT: audio data is 32-bit ieee floating point (but will provided
// in 24-bit integers for convenience)
// MODE_HIGH: file was created in "high" mode (information only)
// MODE_FAST: file was created in "fast" mode (information only)
int WavpackGetMode (WavpackContext *wpc)
{
int mode = 0;
if (wpc) {
if (wpc->config.flags & CONFIG_HYBRID_FLAG)
mode |= MODE_HYBRID;
else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
mode |= MODE_LOSSLESS;
if (wpc->lossy_blocks)
mode &= ~MODE_LOSSLESS;
if (wpc->config.flags & CONFIG_FLOAT_DATA)
mode |= MODE_FLOAT;
if (wpc->config.flags & CONFIG_HIGH_FLAG)
mode |= MODE_HIGH;
if (wpc->config.flags & CONFIG_FAST_FLAG)
mode |= MODE_FAST;
}
return mode;
}
// Unpack the specified number of samples from the current file position.
// Note that "samples" here refers to "complete" samples, which would be
// 2 longs for stereo files. The audio data is returned right-justified in
// 32-bit longs in the endian mode native to the executing processor. So,
// if the original data was 16-bit, then the values returned would be
// +/-32k. Floating point data will be returned as 24-bit integers (and may
// also be clipped). The actual number of samples unpacked is returned,
// which should be equal to the number requested unless the end of fle is
// encountered or an error occurs.
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples)
{
WavpackStream *wps = &wpc->stream;
uint32_t bcount, samples_unpacked = 0, samples_to_unpack;
int num_channels = wpc->config.num_channels;
while (samples) {
if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
bcount = read_next_header (wpc->infile, &wps->wphdr);
if (bcount == (uint32_t) -1)
break;
if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
if (!unpack_init (wpc))
break;
}
if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
continue;
if (wps->sample_index < wps->wphdr.block_index) {
samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
if (samples_to_unpack > samples)
samples_to_unpack = samples;
wps->sample_index += samples_to_unpack;
samples_unpacked += samples_to_unpack;
samples -= samples_to_unpack;
if (wpc->reduced_channels)
samples_to_unpack *= wpc->reduced_channels;
else
samples_to_unpack *= num_channels;
while (samples_to_unpack--)
*buffer++ = 0;
continue;
}
samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
if (samples_to_unpack > samples)
samples_to_unpack = samples;
unpack_samples (wpc, buffer, samples_to_unpack);
if (wpc->reduced_channels)
buffer += samples_to_unpack * wpc->reduced_channels;
else
buffer += samples_to_unpack * num_channels;
samples_unpacked += samples_to_unpack;
samples -= samples_to_unpack;
if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
if (check_crc_error (wpc))
wpc->crc_errors++;
}
if (wps->sample_index == wpc->total_samples)
break;
}
return samples_unpacked;
}
// Get total number of samples contained in the WavPack file, or -1 if unknown
uint32_t WavpackGetNumSamples (WavpackContext *wpc)
{
return wpc ? wpc->total_samples : (uint32_t) -1;
}
// Get the current sample index position, or -1 if unknown
uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
{
if (wpc)
return wpc->stream.sample_index;
return (uint32_t) -1;
}
// Get the number of errors encountered so far
int WavpackGetNumErrors (WavpackContext *wpc)
{
return wpc ? wpc->crc_errors : 0;
}
// return TRUE if any uncorrected lossy blocks were actually written or read
int WavpackLossyBlocks (WavpackContext *wpc)
{
return wpc ? wpc->lossy_blocks : 0;
}
// Returns the sample rate of the specified WavPack file
uint32_t WavpackGetSampleRate (WavpackContext *wpc)
{
return wpc ? wpc->config.sample_rate : 44100;
}
// Returns the number of channels of the specified WavPack file. Note that
// this is the actual number of channels contained in the file, but this
// version can only decode the first two.
int WavpackGetNumChannels (WavpackContext *wpc)
{
return wpc ? wpc->config.num_channels : 2;
}
// Returns the actual number of valid bits per sample contained in the
// original file, which may or may not be a multiple of 8. Floating data
// always has 32 bits, integers may be from 1 to 32 bits each. When this
// value is not a multiple of 8, then the "extra" bits are located in the
// LSBs of the results. That is, values are right justified when unpacked
// into longs, but are left justified in the number of bytes used by the
// original data.
int WavpackGetBitsPerSample (WavpackContext *wpc)
{
return wpc ? wpc->config.bits_per_sample : 16;
}
// Returns the number of bytes used for each sample (1 to 4) in the original
// file. This is required information for the user of this module because the
// audio data is returned in the LOWER bytes of the long buffer and must be
// left-shifted 8, 16, or 24 bits if normalized longs are required.
int WavpackGetBytesPerSample (WavpackContext *wpc)
{
return wpc ? wpc->config.bytes_per_sample : 2;
}
// This function will return the actual number of channels decoded from the
// file (which may or may not be less than the actual number of channels, but
// will always be 1 or 2). Normally, this will be the front left and right
// channels of a multi-channel file.
int WavpackGetReducedChannels (WavpackContext *wpc)
{
if (wpc)
return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
else
return 2;
}
// Read from current file position until a valid 32-byte WavPack 4.0 header is
// found and read into the specified pointer. The number of bytes skipped is
// returned. If no WavPack header is found within 1 meg, then a -1 is returned
// to indicate the error. No additional bytes are read past the header and it
// is returned in the processor's native endian mode. Seeking is not required.
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr)
{
char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
uint32_t bytes_skipped = 0;
int bleft;
while (1) {
if (sp < ep) {
bleft = ep - sp;
memcpy (buffer, sp, bleft);
}
else
bleft = 0;
if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (int32_t) sizeof (*wphdr) - bleft)
return -1;
sp = buffer;
if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
!(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 &&
sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff)) {
memcpy (wphdr, buffer, sizeof (*wphdr));
little_endian_to_native (wphdr, WavpackHeaderFormat);
return bytes_skipped;
}
while (sp < ep && *sp != 'w')
sp++;
if ((bytes_skipped += sp - buffer) > 1048576L)
return -1;
}
}