Yeah, the problem has been identified before, but isn't one of those things that was ever pursued to any serious extent.
Please explain how the EAC's wave processor calculates CRCs when instructed to ignore null samples. I'm interested in knowing.
OK, so I'll continue Thank u for your answer!
Of course, I couldn't complete this job w/o some diassembly works, that, MAYBE violate the EAC license agreement concerned reverse engeneering and so on. But since these digs lead us to the Truth, I think it's not the time to call for lawmakers.
In the programmer terms, let RIP_CRC(bool bUseFlag) be the macro that calculates CRC while ripping CDs, and WAV_ED_CRC(bool bUseFlag) be the macro that calculates CRC in WAVE Editor. The parameter bUseFlag is the "No use of nul samples..." checkbox state.
So, in these terms, we have that
RIP_CRC(false) = WAV_ED, _CRC(false)
RIP_CRC(true) != WAV_ED_CRC(true) (!!! WTF??? !!!)
The solution of this inconsistency lies in the algorythm of WAV_ED_CRC(true) that is buggy (!). And You may easily check this. Take a stereo WAVe file, and calculate CRC using WAVE Editor. You get value CRC=X. Then, modify ANY nonzero sample on RIGHT channel of this file (let us consider that L word is the lower, and R is the higher one in DWORD sample representation). And then calculate it again. You get the SAME value X.
But, obviously, this cannot be true if the procedure works fine.
Here is the assembly of the WAV_ED_CRC(true) [buggy]
(the listing is from IDA Pro 5.0)
.text:0045E520; int __stdcall proc_CRC_Calc_BUF_Ignore_Word_Zeros_S1(int count,int p_CRC,int pBuffer,int old_CRC)
.text:0045E520 proc_CRC_Calc_BUF_Ignore_Word_Zeros_S1 proc near
.text:0045E520 count = dword ptr 8
.text:0045E520 p_CRC = dword ptr 0Ch
.text:0045E520 pBuffer = dword ptr 10h
.text:0045E520 old_CRC = dword ptr 14h
.text:0045E520
.text:0045E520 push ebp
.text:0045E521 mov ebp, esp
.text:0045E523 push ebx
.text:0045E524 push esi
.text:0045E525 push edi
.text:0045E526 push eax
.text:0045E527 push ebx
.text:0045E528 push ecx
.text:0045E529 push edx
.text:0045E52A push esi
.text:0045E52B push edi
.text:0045E52C mov esi, [ebp+old_CRC]
.text:0045E52F mov edi, [ebp+pBuffer]
.text:0045E532 mov edx, [ebp+p_CRC]
.text:0045E535 mov eax, [ebp+count]
.text:0045E538 mov ecx, [edx]
.text:0045E53A
.text:0045E53A cycle:
; ---------------------------------------------------------
; here we obtain
; only lower word of [edi], that is L-R-sample
; the higher word is unused
; ---------------------------------------------------------
.text:0045E53A mov bx, [edi]
.text:0045E53D cmp bx, 0
.text:0045E541 jz short end_if__1
.text:0045E543 push eax
.text:0045E544 push edx
.text:0045E545 push ecx
.text:0045E546 call proc_CRC_TwoByte_BX_ptr_ESI
.text:0045E54B pop ecx
.text:0045E54C pop edx
.text:0045E54D pop eax
.text:0045E54E mov bx, [edi]
.text:0045E551 cmp bx, 32768
.text:0045E556 jnz short end_if__0
.text:0045E558 mov bx, 8001h
.text:0045E55C
.text:0045E55C end_if__0:
.text:0045E55C cmp bx, cx
.text:0045E55F jle short end_if__1
.text:0045E561 mov cx, bx
.text:0045E564
.text:0045E564 end_if__1:
.text:0045E564 ror ecx, 10h
.text:0045E567 cmp bx, cx
.text:0045E56A jge short end_if__2
.text:0045E56C mov cx, bx
.text:0045E56F
.text:0045E56F end_if__2:
.text:0045E56F ror ecx, 10h
; ---------------------------------------------------------
; we increment EDI by 4, so we skip right (or left?) channel
; ---------------------------------------------------------
.text:0045E572 add edi, 4
.text:0045E575 sub eax, 1
.text:0045E578 cmp eax, 0
.text:0045E57B jge short cycle
.text:0045E57D mov [edx], ecx
.text:0045E57F pop edi
.text:0045E580 pop esi
.text:0045E581 pop edx
.text:0045E582 pop ecx
.text:0045E583 pop ebx
.text:0045E584 pop eax
.text:0045E585 pop edi
.text:0045E586 pop esi
.text:0045E587 pop ebx
.text:0045E588 pop ebp
.text:0045E589 retn 10h
.text:0045E589 proc_CRC_Calc_BUF_Ignore_Word_Zeros_S1 endp
;
------------------------------------------------------------------------
And here is the assembly of the WAV_ED_CRC(false) [normal, non-buggy]
.text:0045E590 proc_CRC_Calc_BUF_NoIgnore_Word_Zeros_S2 proc near
.text:0045E590
.text:0045E590 arg_0 = dword ptr 8
.text:0045E590 arg_4 = dword ptr 0Ch
.text:0045E590 arg_8 = dword ptr 10h
.text:0045E590 arg_C = dword ptr 14h
.text:0045E590
.text:0045E590 push ebp
.text:0045E591 mov ebp, esp
.text:0045E593 push ebx
.text:0045E594 push esi
.text:0045E595 push edi
.text:0045E596 push eax
.text:0045E597 push ebx
.text:0045E598 push ecx
.text:0045E599 push edx
.text:0045E59A push esi
.text:0045E59B push edi
.text:0045E59C mov esi, [ebp+arg_C]
.text:0045E59F mov edi, [ebp+arg_8]
.text:0045E5A2 mov edx, [ebp+arg_4]
.text:0045E5A5 mov eax, [ebp+arg_0]
.text:0045E5A8 mov ecx, [edx]
.text:0045E5AA
.text:0045E5AA loc_45E5AA:
.text:0045E5AA push eax
.text:0045E5AB push edx
.text:0045E5AC push ecx
; -----------------------------------
; calculate left channel (lower word)
; -----------------------------------
.text:0045E5AD mov bx, [edi]
.text:0045E5B0 call proc_CRC_TwoByte_BX_ptr_ESI
; -----------------------------------
; calculate left channel (high word)
; -----------------------------------
.text:0045E5B5 mov bx, [edi+2]
.text:0045E5B9 call proc_CRC_TwoByte_BX_ptr_ESI
.text:0045E5BE pop ecx
.text:0045E5BF pop edx
.text:0045E5C0 pop eax
.text:0045E5C1 mov bx, [edi]
.text:0045E5C4 cmp bx, 8000h
.text:0045E5C9 jnz short loc_45E5CF
.text:0045E5CB mov bx, 8001h
.text:0045E5CF
.text:0045E5CF loc_45E5CF:
.text:0045E5CF cmp bx, cx
.text:0045E5D2 jle short loc_45E5D7
.text:0045E5D4 mov cx, bx
.text:0045E5D7
.text:0045E5D7 loc_45E5D7:
.text:0045E5D7 ror ecx, 10h
.text:0045E5DA cmp bx, cx
.text:0045E5DD jge short loc_45E5E2
.text:0045E5DF mov cx, bx
.text:0045E5E2
.text:0045E5E2 loc_45E5E2:
.text:0045E5E2 ror ecx, 10h
.text:0045E5E5 add edi, 4
.text:0045E5E8 sub eax, 1
.text:0045E5EB cmp eax, 0
.text:0045E5EE jge short loc_45E5AA
.text:0045E5F0 mov [edx], ecx
.text:0045E5F2 pop edi
.text:0045E5F3 pop esi
.text:0045E5F4 pop edx
.text:0045E5F5 pop ecx
.text:0045E5F6 pop ebx
.text:0045E5F7 pop eax
.text:0045E5F8 pop edi
.text:0045E5F9 pop esi
.text:0045E5FA pop ebx
.text:0045E5FB pop ebp
.text:0045E5FC retn 10h
.text:0045E5FC proc_CRC_Calc_BUF_NoIgnore_Word_Zeros_S2 endp
Please notice that these routines are different (maybe this is done so for optimisations) (well, my routine written completely in MASM32 works quicker )
Here are some source code for PROPER CRC calculations...
http://dmvn.myftp.org/soft/wavcrc32-gui-0.11-only.rar [w/o SOURCE, optimized version in MASM]
http://dmvn.myftp.org/soft/wavcrc32-conso...22-gui-0.11.rar [C/C++ complete source + console/GUI executables]
OK, now you know all the Truth. At least, about CRC calculations in EAC.
A few words to complete our digs and get up to the surface. Some time ago I've reported this to Andre via mailing to eac@exactaudiocopy.org, but there were no answer, so I'm not sure that my mail was delivered.
Anyway, greynol, I hope this bug will be fixed. The solution is easy as multiply 2 by 2 So we should only verify that Andre knows about it