#167050 - DiscoStew - Fri Feb 27, 2009 8:23 pm
After eKid released his ms-adpcm decoder using assembly for fast stream decoding, I wanted to improve my own ima-adpcm decoding by using assembly as well. With his permission, I used the general template from his decoder, made some changes to some structures, and made the decoding code from scratch in assembly, which took some time to do because of my inexperience with dealing with assembly upfront. It all works, but because of my inexperience, I have no idea if there is any room for improving it. So, in order for me to learn, I've posted the decoding core below, and maybe some of you could teach me the ropes.
The interface mimics eKid's own ms-adpcm decoder, but the input data pointer is for my own structure, also listed below. If there are any question as to why I'm doing X and Y, just ask me.
NOTE: For those currently using my C/C++ implemented ima-adpcm decoder, do not switch to using this, because the structuring is different. When improvements are made (if any can be) and code is organized, I will release it.
_________________
DS - It's all about DiscoStew
The interface mimics eKid's own ms-adpcm decoder, but the input data pointer is for my own structure, also listed below. If there are any question as to why I'm doing X and Y, just ask me.
NOTE: For those currently using my C/C++ implemented ima-adpcm decoder, do not switch to using this, because the structuring is different. When improvements are made (if any can be) and code is organized, I will release it.
Code: |
typedef struct t_IMA_Adpcm_Data { int curSamps; int data1, step1, samp1; int data2, step2, samp2; } IMA_Adpcm_Data; |
Code: |
.global decode_stereo_ima_adpcm .text .arm .align #define cur r0 #define da1 r4 #define st1 r5 #define sa1 r6 #define da2 r7 #define st2 r8 #define sa2 r9 #define ta r10 #define tb r11 #define tc r12 #define istab r14 #define src r1 #define dest r2 #define iter r3 /* SampXCode = Stream_CurSamples & 0xF; Stream_CurSamples >>= 4; Diff = (((( SampXCode & 0x7 ) << 1 ) + 1 ) * STREAM_StepTab[ Stream_StepIndex ]) >> 3; Stream_StepIndex += STREAM_IndexTab[ SampXCode ]; Stream_LastSample += ( SampXCode & 0x8 ? -Diff : Diff ); if( Stream_StepIndex > 88 ) Stream_StepIndex = 88; if( Stream_StepIndex < 0 ) Stream_StepIndex = 0; if( Stream_LastSample > 32767 ) Stream_LastSample = 32767; if( Stream_LastSample <= -32768 ) Stream_LastSample = -32768; *target++ = Stream_LastSample; */ /************************************************************* * * * decode_stereo_ima_adpcm( data, source, target, iterations ) * * * *************************************************************/ decode_stereo_ima_adpcm: push {r0,r4-r11,lr} ldmia r0, {cur,da1,st1,sa1,da2,st2,sa2} adr istab, Index_Step_Table .examine_cur: cmp cur, #0 beq .reloadwords .decode_word_loop: /*************** Left channel *********************/ ldr tc, [istab, st1, lsl#2] // tc = Step_Index_Table[ Step_Index1 ] and ta, da1, #15 // ta = CurSamples1 & 0xF lsr da1, da1, #4 // CurSamples1 >>= 4 and tb, ta, #7 // tb = ta & 0x7 cmp ta, #8 // Is ta >= 8 (ExamineA) add ta, #1 // ta += 1 ldr ta, [istab, -ta, lsl#2] // ta = StepIndex_Table[ -ta ] add st1, ta // Step_Index1 += ta lsl tb, #1 // Diff = ((( tb << 1 ) + 1) * tc) >> 3 add tb, #1 smulbb ta, tb, tc asr ta, #3 subge sa1, ta // Samp1 -= ta if ExamineA is true addlt sa1, ta // Samp1 += ta if ExamineA is false /*************** Right channel ********************/ ldr tc, [istab, st2, lsl#2] // tc = Step_Index_Table[ Step_Index2 ] and ta, da2, #15 // ta = CurSamples2 & 0xF lsr da2, da2, #4 // CurSamples2 >>= 4 and tb, ta, #7 // tb = ta & 0x7 cmp ta, #8 // Is ta >= 8 (ExamineB) add ta, #1 // ta += 1 ldr ta, [istab, -ta, lsl#2] // ta = StepIndex_Table[ -ta ] add st2, ta // Step_Index2 += ta lsl tb, #1 // Diff = ((( tb << 1 ) + 1) * tc) >> 3 add tb, #1 smulbb ta, tb, tc asr ta, #3 subge sa2, ta // Samp2 -= ta if ExamineB is true addlt sa2, ta // Samp2 += ta if ExamineB is false /************* Clamp Step Indexes *******************/ cmp st1, #89 cmplt st2, #89 bge .satihi 1: cmp st1, #0 cmpge st2, #0 blt .satilo /**************** Clamp Samples *********************/ 2: cmp sa1, #32768 cmplt sa2, #32768 bge .sathi 3: cmp sa1, #-32768 cmpge sa2, #-32768 blt .satlo /*************** Write Samples *********************/ 4: strh sa1, [dest], #2 strh sa2, [dest], #2 sub cur, #1 subs iter, #1 bne .examine_cur pop {ta} stmia ta, {cur,da1,st1,sa1,da2,st2,sa2} pop {r4-r11,pc} .reloadwords: mov cur, #8 ldr da1, [src], #4 ldr da2, [src], #4 b .decode_word_loop .satihi: cmp st1, #89 ldrge st1, [istab, #-68] cmp st2, #89 ldrge st2, [istab, #-68] b 1b .satilo: cmp st1, #0 ldrlt st1, [istab, #-72] cmp st2, #0 ldrlt st2, [istab, #-72] b 2b .sathi: cmp sa1, #32768 ldrge sa1, [istab, #352] cmp sa2, #32768 ldrge sa2, [istab, #352] b 3b .satlo: cmp sa1, #-32768 ldrlt sa1, [istab, #356] cmp sa2, #-32768 ldrlt sa2, [istab, #356] b 4b .word 0 .word 88 .word 8, 6, 4, 2, -1, -1, -1, -1 .word 8, 6, 4, 2, -1, -1, -1, -1 Index_Step_Table: .word 7, 8, 9, 10, 11, 12, 13, 14 .word 16, 17, 19, 21, 23, 25, 28, 31 .word 34, 37, 41, 45, 50, 55, 60, 66 .word 73, 80, 88, 97, 107, 118, 130, 143 .word 157, 173, 190, 209, 230, 253, 279, 307 .word 337, 371, 408, 449, 494, 544, 598, 658 .word 724, 796, 876, 963, 1060, 1166, 1282, 1411 .word 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024 .word 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484 .word 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899 .word 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794 .word 32767 .word -32768 |
_________________
DS - It's all about DiscoStew