annotate core/FormatConvert.S @ 511:633ade85e798 prerelease

Cleared build_pd_heavy
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 22 Jun 2016 04:53:06 +0100
parents f7b19ea31bbb
children
rev   line source
andrewm@318 1 @
andrewm@318 2 @ FormatConvert.S
andrewm@318 3 @
andrewm@318 4 @ NEON-based vector functions for converting data between int
andrewm@318 5 @ and float with clipping and optional level scaling.
andrewm@318 6 @ Written in assembly for performance reasons.
andrewm@318 7 @
andrewm@318 8 @ Bela: http://bela.io
andrewm@318 9 @
andrewm@318 10 @ (c) 2016 Andrew McPherson
andrewm@318 11 @ Centre for Digital Music
andrewm@318 12 @ Queen Mary University of London
andrewm@318 13 @
andrewm@318 14
andrewm@318 15 .syntax unified
andrewm@318 16 .arch armv7-a
andrewm@318 17 .fpu neon
andrewm@318 18
andrewm@318 19 @ void int16_to_float_audio(int numSamples, int16_t *inBuffer, float *outBuffer);
andrewm@318 20 @
andrewm@318 21 @ Convert 16-bit signed ints to floats between -1.0 and 1.0. Used for audio input.
andrewm@318 22 @
andrewm@318 23 @ numSamples should be a multiple of 4 (i.e. with stereo audio, frames should be even)
andrewm@318 24 @ inBuffer should be aligned on an 8-byte boundary.
andrewm@318 25 @ outBuffer should be aligned on a 16-byte boundary.
andrewm@318 26
andrewm@318 27 @ Registers:
andrewm@318 28 @ r0: numSamples How many frames to convert
andrewm@318 29 @ r1: inBuffer Buffer for input samples from ADC
andrewm@318 30 @ r2: outBuffer Buffer to store output samples for render function
andrewm@318 31
andrewm@318 32 dIFAu_Input .dn D0.S16
andrewm@318 33 qIFAu_Expanded .qn Q1.S32
andrewm@318 34 qIFAu_Output .qn Q2.F32
andrewm@318 35 dIFAu_Output_0 .dn D4.F32
andrewm@318 36 dIFAu_Output_1 .dn D5.F32
andrewm@318 37
andrewm@318 38 .align 2
andrewm@318 39 .global int16_to_float_audio
andrewm@318 40 .thumb
andrewm@318 41 .thumb_func
andrewm@318 42 .type int16_to_float_audio, %function
andrewm@318 43 int16_to_float_audio:
andrewm@318 44 lsr r0, r0, #2
andrewm@318 45 lsl r0, r0, #2 @ Clip off the last two bits of numSamples (only multiples of 4 allowed)
andrewm@318 46 cmp r0, #0 @ Check for trivial case: zero samples
andrewm@318 47 it eq
andrewm@318 48 bxeq lr @ Return if that's the case
andrewm@318 49
andrewm@318 50 @ ---- loop: iterate over the number of samples ----
andrewm@318 51 int16_to_float_audio_loop:
andrewm@318 52 vld1 {dIFAu_Input}, [r1]! @ Load four 16-bit signed ints from inBuffer++
andrewm@318 53 vmovl qIFAu_Expanded, dIFAu_Input @ Convert four 16-bit signed ints to 32-bit signed ints
andrewm@318 54 vcvt qIFAu_Output, qIFAu_Expanded, #15 @ Convert four Q17.15 fixed points to floats (equiv. to / 32768)
andrewm@318 55 vst1 {dIFAu_Output_0, dIFAu_Output_1}, [r2]! @ Store floats back into memory
andrewm@318 56
andrewm@318 57 subs r0, r0, #4 @ numSamples -= 4
andrewm@318 58 it gt
andrewm@318 59 bgt int16_to_float_audio_loop @ Loop if numSamples > 0
andrewm@318 60
andrewm@318 61 bx lr
andrewm@318 62
andrewm@318 63
andrewm@318 64
andrewm@318 65 @ void int16_to_float_analog(int numSamples, uint16_t *inBuffer, float *outBuffer);
andrewm@318 66 @
andrewm@318 67 @ Convert 16-bit unsigned ints to floats between 0.0 and 1.0. Used for analog input.
andrewm@318 68 @
andrewm@318 69 @ numSamples should be a multiple of 4 (i.e. integer numFrames at 4 channels)
andrewm@318 70 @ inBuffer should be aligned on an 8-byte boundary.
andrewm@318 71 @ outBuffer should be aligned on a 16-byte boundary.
andrewm@318 72
andrewm@318 73 @ Registers:
andrewm@318 74 @ r0: numSamples How many frames to convert
andrewm@318 75 @ r1: inBuffer Buffer for input samples from ADC
andrewm@318 76 @ r2: outBuffer Buffer to store output samples for render function
andrewm@318 77
andrewm@318 78 dIFAn_Input .dn D0.U16
andrewm@318 79 qIFAn_Expanded .qn Q1.U32
andrewm@318 80 qIFAn_Output .qn Q2.F32
andrewm@318 81 dIFAn_Output_0 .dn D4.F32
andrewm@318 82 dIFAn_Output_1 .dn D5.F32
andrewm@318 83
andrewm@318 84 .align 2
andrewm@318 85 .global int16_to_float_analog
andrewm@318 86 .thumb
andrewm@318 87 .thumb_func
andrewm@318 88 .type int16_to_float_analog, %function
andrewm@318 89 int16_to_float_analog:
andrewm@318 90 lsr r0, r0, #2
andrewm@318 91 lsl r0, r0, #2 @ Clip off the last two bits of numSamples (only multiples of 4 allowed)
andrewm@318 92 cmp r0, #0 @ Check for trivial case: zero samples
andrewm@318 93 it eq
andrewm@318 94 bxeq lr @ Return if that's the case
andrewm@318 95
andrewm@318 96 @ ---- loop: iterate over the number of samples ----
andrewm@318 97 int16_to_float_analog_loop:
andrewm@318 98 vld1 {dIFAn_Input}, [r1]! @ Load four 16-bit signed ints from inBuffer++
andrewm@318 99 vmovl qIFAn_Expanded, dIFAn_Input @ Convert four 16-bit signed ints to 32-bit signed ints
andrewm@318 100 vcvt qIFAn_Output, qIFAn_Expanded, #16 @ Convert four Q16.16 fixed points to floats (equiv. to / 65536)
andrewm@318 101 vst1 {dIFAn_Output_0, dIFAn_Output_1}, [r2]! @ Store floats back into memory
andrewm@318 102
andrewm@318 103 subs r0, r0, #4 @ numSamples -= 4
andrewm@318 104 it gt
andrewm@318 105 bgt int16_to_float_analog_loop @ Loop if numSamples > 0
andrewm@318 106
andrewm@318 107 bx lr
andrewm@318 108
andrewm@318 109
andrewm@318 110 @ void float_to_int16_audio(int numSamples, float *inBuffer, int16_t *outBuffer);
andrewm@318 111 @
andrewm@318 112 @ Convert floats between -1.0 and 1.0 to 16-bit signed ints, with saturation.
andrewm@318 113 @ Used for audio output.
andrewm@318 114 @
andrewm@318 115 @ numSamples should be a multiple of 4 (i.e. with stereo audio, frames should be even)
andrewm@318 116 @ inBuffer should be aligned on a 16-byte boundary.
andrewm@318 117 @ outBuffer should be aligned on an 8-byte boundary.
andrewm@318 118
andrewm@318 119 @ Registers:
andrewm@318 120 @ r0: numSamples How many frames to convert
andrewm@318 121 @ r1: inBuffer Buffer for input samples from render function
andrewm@318 122 @ r2: outBuffer Buffer to store output samples for DAC
andrewm@318 123
andrewm@318 124 qFIAu_Input .qn Q0.F32
andrewm@318 125 dFIAu_Input_0 .dn D0.F32
andrewm@318 126 dFIAu_Input_1, .dn D1.F32
andrewm@318 127 qFIAu_Converted .qn Q1.S32
andrewm@318 128 dFIAu_Narrowed .dn D4.S16
andrewm@318 129
andrewm@318 130 .align 2
andrewm@318 131 .global float_to_int16_audio
andrewm@318 132 .thumb
andrewm@318 133 .thumb_func
andrewm@318 134 .type float_to_int16_audio, %function
andrewm@318 135
andrewm@318 136 float_to_int16_audio:
andrewm@318 137 lsr r0, r0, #2
andrewm@318 138 lsl r0, r0, #2 @ Clip off the last two bits of numSamples (only multiples of 4 allowed)
andrewm@318 139 cmp r0, #0 @ Check for trivial case: zero samples
andrewm@318 140 it eq
andrewm@318 141 bxeq lr @ Return if that's the case
andrewm@318 142
andrewm@318 143 @ ---- loop: iterate over the number of samples ----
andrewm@318 144 float_to_int16_audio_loop:
andrewm@318 145 vld1 {dFIAu_Input_0, dFIAu_Input_1}, [r1]! @ Load four floats from inBuffer++
andrewm@318 146 vcvt qFIAu_Converted, qFIAu_Input, #15 @ Convert four floats into four Q17.15 fixed points (equiv. to * 32768)
andrewm@318 147 @ This will truncate the result to a 32-bit representable value
andrewm@318 148 vqmovn dFIAu_Narrowed, qFIAu_Converted @ Convert four 32-bit signed ints to 16-bit signed ints, with saturation
andrewm@318 149 vst1 {dFIAu_Narrowed}, [r2]! @ Store ints back into memory
andrewm@318 150
andrewm@318 151 subs r0, r0, #4 @ numSamples -= 4
andrewm@318 152 it gt
andrewm@318 153 bgt float_to_int16_audio_loop @ Loop if numSamples > 0
andrewm@318 154
andrewm@318 155 bx lr
andrewm@318 156
andrewm@318 157
andrewm@318 158 @ void float_to_int16_analog(int numSamples, float *inBuffer, uint16_t *outBuffer);
andrewm@318 159 @
andrewm@318 160 @ Convert floats between 0.0 and 1.0 to 16-bit unsigned ints, with saturation.
andrewm@318 161 @ Used for analog output.
andrewm@318 162 @
andrewm@318 163 @ numSamples should be a multiple of 4 (i.e. with stereo audio, frames should be even)
andrewm@318 164 @ inBuffer should be aligned on a 16-byte boundary.
andrewm@318 165 @ outBuffer should be aligned on an 8-byte boundary.
andrewm@318 166
andrewm@318 167 @ Registers:
andrewm@318 168 @ r0: numSamples How many frames to convert
andrewm@318 169 @ r1: inBuffer Buffer for input samples from render function
andrewm@318 170 @ r2: outBuffer Buffer to store output samples for DAC
andrewm@318 171
andrewm@318 172 qFIAn_Input .qn Q0.F32
andrewm@318 173 dFIAn_Input_0 .dn D0.F32
andrewm@318 174 dFIAn_Input_1, .dn D1.F32
andrewm@318 175 qFIAn_Converted .qn Q1.U32
andrewm@318 176 dFIAn_Narrowed .dn D4.U16
andrewm@318 177
andrewm@318 178 .align 2
andrewm@318 179 .global float_to_int16_analog
andrewm@318 180 .thumb
andrewm@318 181 .thumb_func
andrewm@318 182 .type float_to_int16_analog, %function
andrewm@318 183
andrewm@318 184 float_to_int16_analog:
andrewm@318 185 lsr r0, r0, #2
andrewm@318 186 lsl r0, r0, #2 @ Clip off the last two bits of numSamples (only multiples of 4 allowed)
andrewm@318 187 cmp r0, #0 @ Check for trivial case: zero samples
andrewm@318 188 it eq
andrewm@318 189 bxeq lr @ Return if that's the case
andrewm@318 190
andrewm@318 191 @ ---- loop: iterate over the number of samples ----
andrewm@318 192 float_to_int16_analog_loop:
andrewm@318 193 vld1 {dFIAn_Input_0, dFIAn_Input_1}, [r1]! @ Load four floats from inBuffer++
andrewm@318 194 vcvt qFIAn_Converted, qFIAn_Input, #16 @ Convert four floats into four Q16.16 fixed points (equiv. to * 65536)
andrewm@318 195 @ This will truncate the result to a 32-bit representable value
andrewm@318 196 vqmovn dFIAn_Narrowed, qFIAn_Converted @ Convert four 32-bit unsigned ints to 16-bit unsigned ints, with saturation
andrewm@318 197 vst1 {dFIAn_Narrowed}, [r2]! @ Store ints back into memory
andrewm@318 198
andrewm@318 199 subs r0, r0, #4 @ numSamples -= 4
andrewm@318 200 it gt
andrewm@318 201 bgt float_to_int16_analog_loop @ Loop if numSamples > 0
andrewm@318 202
andrewm@318 203 bx lr
andrewm@318 204