mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
applied patch from Richie Nyhus to convert CRLF to LF, as it should be
This commit is contained in:
parent
61d18702f6
commit
4004d13b48
922
src/engine/external/wavpack/arm.S
vendored
922
src/engine/external/wavpack/arm.S
vendored
|
@ -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}
|
||||
|
||||
|
|
982
src/engine/external/wavpack/arml.S
vendored
982
src/engine/external/wavpack/arml.S
vendored
|
@ -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}
|
||||
|
||||
|
|
280
src/engine/external/wavpack/bits.c
vendored
280
src/engine/external/wavpack/bits.c
vendored
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
1050
src/engine/external/wavpack/coldfire.S
vendored
1050
src/engine/external/wavpack/coldfire.S
vendored
File diff suppressed because it is too large
Load diff
100
src/engine/external/wavpack/float.c
vendored
100
src/engine/external/wavpack/float.c
vendored
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
50
src/engine/external/wavpack/license.txt
vendored
50
src/engine/external/wavpack/license.txt
vendored
|
@ -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.
|
||||
|
|
210
src/engine/external/wavpack/metadata.c
vendored
210
src/engine/external/wavpack/metadata.c
vendored
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
136
src/engine/external/wavpack/readme.txt
vendored
136
src/engine/external/wavpack/readme.txt
vendored
|
@ -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
|
||||
|
|
1570
src/engine/external/wavpack/unpack.c
vendored
1570
src/engine/external/wavpack/unpack.c
vendored
File diff suppressed because it is too large
Load diff
576
src/engine/external/wavpack/wavpack.h
vendored
576
src/engine/external/wavpack/wavpack.h
vendored
|
@ -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);
|
||||
|
|
1120
src/engine/external/wavpack/words.c
vendored
1120
src/engine/external/wavpack/words.c
vendored
File diff suppressed because it is too large
Load diff
702
src/engine/external/wavpack/wputils.c
vendored
702
src/engine/external/wavpack/wputils.c
vendored
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue