A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 255 lines 8.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2007-2010 Michael Sevakis (jhMikeS) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#if !SPC_NOINTERP 22 23#define SPC_GAUSSIAN_FAST_INTERP 24static inline int gaussian_fast_interp( int16_t const* samples, 25 int32_t position, 26 int16_t const* fwd, 27 int16_t const* rev ) 28{ 29 int output; 30 int t0, t1, t2, t3; 31 32 asm volatile ( 33 "ldrsh %[t0], [%[samp]] \n" 34 "ldrsh %[t2], [%[fwd]] \n" 35 "ldrsh %[t1], [%[samp], #2] \n" 36 "ldrsh %[t3], [%[fwd], #2] \n" 37 "mul %[out], %[t0], %[t2] \n" /* out= fwd[0]*samp[0] */ 38 "ldrsh %[t0], [%[samp], #4] \n" 39 "ldrsh %[t2], [%[rev], #2] \n" 40 "mla %[out], %[t1], %[t3], %[out] \n" /* out+=fwd[1]*samp[1] */ 41 "ldrsh %[t1], [%[samp], #6] \n" 42 "ldrsh %[t3], [%[rev]] \n" 43 "mla %[out], %[t0], %[t2], %[out] \n" /* out+=rev[1]*samp[2] */ 44 "mla %[out], %[t1], %[t3], %[out] \n" /* out+=rev[0]*samp[3] */ 45 : [out]"=&r"(output), 46 [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3) 47 : [fwd]"r"(fwd), [rev]"r"(rev), 48 [samp]"r"(samples + (position >> 12))); 49 50 return output; 51} 52 53#if 0 // first asm block generates "Rd and Rm should be different in mul" error 54#define SPC_GAUSSIAN_FAST_AMP 55static inline int gaussian_fast_amp( struct voice_t* voice, int output, 56 int* amp_0, int* amp_1 ) 57{ 58 int t0; 59 60 asm volatile ( 61 "mov %[t0], %[out], asr #11 \n" 62 "mul %[out], %[t0], %[envx] \n" 63 : [out]"+r"(output), [t0]"=&r"(t0) 64 : [envx]"r"((int) voice->envx)); 65 66 asm volatile ( 67 "mov %[out], %[out], asr #11 \n" 68 "mul %[a0], %[out], %[v0] \n" 69 "mul %[a1], %[out], %[v1] \n" 70 : [out]"+r"(output), 71 [a0]"=&r"(*amp_0), [a1]"=r"(*amp_1) 72 : [v0]"r"((int) voice->volume [0]), 73 [v1]"r"((int) voice->volume [1])); 74 75 return output; 76} 77#endif 78 79#define SPC_GAUSSIAN_SLOW_INTERP 80static inline int gaussian_slow_interp( int16_t const* samples, 81 int32_t position, 82 int16_t const* fwd, 83 int16_t const* rev ) 84{ 85 int output; 86 int t0, t1, t2, t3; 87 88 asm volatile ( 89 "ldrsh %[t0], [%[samp]] \n" 90 "ldrsh %[t2], [%[fwd]] \n" 91 "ldrsh %[t1], [%[samp], #2] \n" 92 "ldrsh %[t3], [%[fwd], #2] \n" 93 "mul %[out], %[t2], %[t0] \n" /* fwd[0]*samp[0] */ 94 "ldrsh %[t2], [%[rev], #2] \n" 95 "mul %[t0], %[t3], %[t1] \n" /* fwd[1]*samp[1] */ 96 "ldrsh %[t1], [%[samp], #4] \n" 97 "mov %[out], %[out], asr #12 \n" 98 "ldrsh %[t3], [%[rev]] \n" 99 "mul %[t2], %[t1], %[t2] \n" /* rev[1]*samp[2] */ 100 "ldrsh %[t1], [%[samp], #6] \n" 101 "add %[t0], %[out], %[t0], asr #12 \n" 102 "mul %[t3], %[t1], %[t3] \n" /* rev[0]*samp[3] */ 103 "add %[t2], %[t0], %[t2], asr #12 \n" 104 "mov %[t2], %[t2], lsl #17 \n" 105 "mov %[t3], %[t3], asr #12 \n" 106 "mov %[t3], %[t3], asl #1 \n" 107 "add %[out], %[t3], %[t2], asr #16 \n" 108 : [out]"=&r"(output), 109 [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3) 110 : [fwd]"r"(fwd), [rev]"r"(rev), 111 [samp]"r"(samples + (position >> 12))); 112 113 return CLAMP16( output ); 114} 115 116#define SPC_GAUSSIAN_SLOW_AMP 117static inline int gaussian_slow_amp( struct voice_t* voice, int output, 118 int* amp_0, int* amp_1 ) 119{ 120 int t0; 121 122 asm volatile ( 123 "mul %[t0], %[out], %[envx]" 124 : [t0]"=r"(t0) 125 : [out]"r"(output), [envx]"r"((int) voice->envx)); 126 asm volatile ( 127 "mov %[t0], %[t0], asr #11 \n" 128 "bic %[t0], %[t0], #0x1 \n" 129 "mul %[a0], %[t0], %[v0] \n" 130 "mul %[a1], %[t0], %[v1] \n" 131 : [t0]"+r"(t0), 132 [a0]"=&r"(*amp_0), [a1]"=r"(*amp_1) 133 : [v0]"r"((int) voice->volume [0]), 134 [v1]"r"((int) voice->volume [1])); 135 136 return t0; 137} 138 139#else /* SPC_NOINTERP */ 140 141#define SPC_LINEAR_INTERP 142static inline int linear_interp( int16_t const* samples, int32_t position ) 143{ 144 int output = (int) samples; 145 int y1; 146 147 asm volatile( 148 "mov %[y1], %[f], lsr #12 \n" 149 "eor %[f], %[f], %[y1], lsl #12 \n" 150 "add %[y1], %[y0], %[y1], lsl #1 \n" 151 "ldrsh %[y0], [%[y1], #2] \n" 152 "ldrsh %[y1], [%[y1], #4] \n" 153 "sub %[y1], %[y1], %[y0] \n" 154 "mul %[f], %[y1], %[f] \n" 155 "add %[y0], %[y0], %[f], asr #12 \n" 156 : [f]"+r"(position), [y0]"+r"(output), [y1]"=&r"(y1)); 157 158 return output; 159} 160 161#define SPC_LINEAR_AMP 162static inline int linear_amp( struct voice_t* voice, int output, 163 int* amp_0, int* amp_1 ) 164{ 165 int t0; 166 167 asm volatile( 168 "mul %[t0], %[out], %[envx]" 169 : [t0]"=&r"(t0) 170 : [out]"r"(output), [envx]"r"(voice->envx)); 171 asm volatile( 172 "mov %[t0], %[t0], asr #11 \n" 173 "mul %[a1], %[t0], %[v1] \n" 174 "mul %[a0], %[t0], %[v0] \n" 175 : [t0]"+r"(t0), 176 [a0]"=&r"(*amp_0), [a1]"=&r"(*amp_1) 177 : [v0]"r"((int) voice->volume [0]), 178 [v1]"r"((int) voice->volume [1])); 179 180 return t0; 181} 182 183#endif /* !SPC_NOINTERP */ 184 185 186#if !SPC_NOECHO 187 188#define SPC_DSP_ECHO_APPLY 189 190/* Echo filter history */ 191static int32_t fir_buf[FIR_BUF_CNT] IBSS_ATTR_SPC 192 __attribute__(( aligned(FIR_BUF_ALIGN*1) )); 193 194static inline void echo_init( struct Spc_Dsp* this ) 195{ 196 this->fir.ptr = fir_buf; 197 ci->memset( fir_buf, 0, sizeof fir_buf ); 198} 199 200static inline void echo_apply( struct Spc_Dsp* this, uint8_t *echo_ptr, 201 int* out_0, int* out_1 ) 202{ 203 int t0 = GET_LE16SA( echo_ptr ); 204 int t1 = GET_LE16SA( echo_ptr + 2 ); 205 206 /* Keep last 8 samples */ 207 int32_t *fir_ptr; 208 asm volatile ( 209 "add %[p], %[t_p], #8 \n" 210 "bic %[t_p], %[p], %[mask] \n" 211 "str %[t0], [%[p], #-8] \n" 212 "str %[t1], [%[p], #-4] \n" 213 /* duplicate at +8 eliminates wrap checking below */ 214 "str %[t0], [%[p], #56] \n" 215 "str %[t1], [%[p], #60] \n" 216 : [p]"=&r"(fir_ptr), [t_p]"+r"(this->fir.ptr) 217 : [t0]"r"(t0), [t1]"r"(t1), [mask]"i"(~FIR_BUF_MASK)); 218 219 int32_t *fir_coeff = this->fir.coeff; 220 221 asm volatile ( 222 "ldmia %[c]!, { r0-r1 } \n" 223 "ldmia %[p]!, { r4-r5 } \n" 224 "mul %[acc0], r0, %[acc0] \n" 225 "mul %[acc1], r0, %[acc1] \n" 226 "mla %[acc0], r4, r1, %[acc0] \n" 227 "mla %[acc1], r5, r1, %[acc1] \n" 228 "ldmia %[c]!, { r0-r1 } \n" 229 "ldmia %[p]!, { r2-r5 } \n" 230 "mla %[acc0], r2, r0, %[acc0] \n" 231 "mla %[acc1], r3, r0, %[acc1] \n" 232 "mla %[acc0], r4, r1, %[acc0] \n" 233 "mla %[acc1], r5, r1, %[acc1] \n" 234 "ldmia %[c]!, { r0-r1 } \n" 235 "ldmia %[p]!, { r2-r5 } \n" 236 "mla %[acc0], r2, r0, %[acc0] \n" 237 "mla %[acc1], r3, r0, %[acc1] \n" 238 "mla %[acc0], r4, r1, %[acc0] \n" 239 "mla %[acc1], r5, r1, %[acc1] \n" 240 "ldmia %[c]!, { r0-r1 } \n" 241 "ldmia %[p]!, { r2-r5 } \n" 242 "mla %[acc0], r2, r0, %[acc0] \n" 243 "mla %[acc1], r3, r0, %[acc1] \n" 244 "mla %[acc0], r4, r1, %[acc0] \n" 245 "mla %[acc1], r5, r1, %[acc1] \n" 246 : [acc0]"+r"(t0), [acc1]"+r"(t1), 247 [p]"+r"(fir_ptr), [c]"+r"(fir_coeff) 248 : 249 : "r0", "r1", "r2", "r3", "r4", "r5"); 250 251 *out_0 = t0; 252 *out_1 = t1; 253} 254 255#endif /* SPC_NOECHO */