| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 | 
							- /* 
 
-  *  Squeezelite - lightweight headless squeezebox emulator
 
-  *
 
-  *  (c) Adrian Smith 2012-2015, triode1@btinternet.com
 
-  *      Ralph Irving 2015-2017, ralph_irving@hotmail.com
 
-  *
 
-  * This program is free software: you can redistribute it and/or modify
 
-  * it under the terms of the GNU General Public License as published by
 
-  * the Free Software Foundation, either version 3 of the License, or
 
-  * (at your option) any later version.
 
-  * 
 
-  * This program is distributed in the hope that it will be useful,
 
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
-  * GNU General Public License for more details.
 
-  *
 
-  * You should have received a copy of the GNU General Public License
 
-  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-  *
 
-  */
 
- // Scale and pack functions
 
- #include "squeezelite.h"
 
- #define MAX_SCALESAMPLE 0x7fffffffffffLL
 
- #define MIN_SCALESAMPLE -MAX_SCALESAMPLE
 
- // inlining these on windows prevents them being linkable...
 
- #if !WIN
 
- inline 
 
- #endif
 
- s32_t gain(s32_t gain, s32_t sample) {
 
- 	s64_t res = (s64_t)gain * (s64_t)sample;
 
- 	if (res > MAX_SCALESAMPLE) res = MAX_SCALESAMPLE;
 
- 	if (res < MIN_SCALESAMPLE) res = MIN_SCALESAMPLE;
 
- 	return (s32_t) (res >> 16);
 
- }
 
- #if !WIN
 
- inline
 
- #endif
 
- s32_t to_gain(float f) {
 
- 	return (s32_t)(f * 65536.0F);
 
- }
 
- void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, u8_t flags, output_format format) {
 
- 	// in-place copy input samples if mono/combined is used (never happens with DSD active)
 
- 	if ((flags & MONO_LEFT) && (flags & MONO_RIGHT)) {
 
- 		s32_t *ptr = inputptr;
 
- 		frames_t count = cnt;
 
- 		while (count--) {
 
- 			// use 64 bits integer for purists but should really not care
 
- 			*ptr = *(ptr + 1) = ((s64_t) *ptr + (s64_t) *(ptr + 1)) / 2;
 
- 			ptr += 2;
 
- 		}
 
- 	} else if (flags & MONO_RIGHT) {
 
- 		s32_t *ptr = inputptr + 1;
 
- 		frames_t count = cnt;
 
- 		while (count--) {
 
- 			*(ptr - 1) = *ptr;
 
- 			ptr += 2;
 
- 		}
 
- 	} else if (flags & MONO_LEFT) {	
 
- 		s32_t *ptr = inputptr;
 
- 		frames_t count = cnt;
 
- 		while (count--) {
 
- 			*(ptr + 1) = *ptr;
 
- 			ptr += 2;
 
- 		}
 
- 	}	
 
- 	
 
- 	switch(format) {
 
- #if DSD
 
- 	case U32_LE:
 
- 		{
 
- #if SL_LITTLE_ENDIAN
 
- 			memcpy(outputptr, inputptr, cnt * BYTES_PER_FRAME);
 
- #else
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- 			while (cnt--) {
 
- 				s32_t lsample = *(inputptr++);
 
- 				s32_t rsample = *(inputptr++);
 
- 				*(optr++) = 
 
- 					(lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
 
- 					(lsample & 0x0000ff00) << 8  | (lsample & 0x000000ff) << 24;
 
- 				*(optr++) = 
 
- 					(rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
 
- 					(rsample & 0x0000ff00) << 8  | (rsample & 0x000000ff) << 24;
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	case U32_BE:
 
- 		{
 
- #if SL_LITTLE_ENDIAN
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- 			while (cnt--) {
 
- 				s32_t lsample = *(inputptr++);
 
- 				s32_t rsample = *(inputptr++);
 
- 				*(optr++) = 
 
- 					(lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
 
- 					(lsample & 0x0000ff00) << 8  | (lsample & 0x000000ff) << 24;
 
- 				*(optr++) = 
 
- 					(rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
 
- 					(rsample & 0x0000ff00) << 8  | (rsample & 0x000000ff) << 24;
 
- 			}
 
- #else
 
- 			memcpy(outputptr, inputptr, cnt * BYTES_PER_FRAME);
 
- #endif
 
- 		}
 
- 		break;
 
- 	case U16_LE:
 
- 		{
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			while (cnt--) {
 
- 				*(optr++) = (*(inputptr) >> 16 & 0x0000ffff) | (*(inputptr + 1) & 0xffff0000);
 
- 				inputptr += 2;
 
- 			}
 
- #else
 
- 			while (cnt--) {
 
- 				s32_t lsample = *(inputptr++);
 
- 				s32_t rsample = *(inputptr++);
 
- 				*(optr++) = 
 
- 					(lsample & 0x00ff0000) << 8 | (lsample & 0xff000000) >> 8 |
 
- 					(rsample & 0x00ff0000) >> 8 | (rsample & 0xff000000) >> 24;
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	case U16_BE:
 
- 		{
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			while (cnt--) {
 
- 				s32_t lsample = *(inputptr++);
 
- 				s32_t rsample = *(inputptr++);
 
- 				*(optr++) = 
 
- 					(lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
 
- 					(rsample & 0xff000000) >> 8 | (rsample & 0x00ff0000) << 8;
 
- 			}
 
- #else
 
- 			while (cnt--) {
 
- 				*(optr++) = (*(inputptr) & 0xffff0000) | (*(inputptr + 1) >> 16 & 0x0000ffff);
 
- 				inputptr += 2;
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	case U8:
 
- 		{
 
- 			u16_t *optr = (u16_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			while (cnt--) {
 
- 				*(optr++) = (u16_t)((*(inputptr) >> 24 & 0x000000ff) | (*(inputptr + 1) >> 16 & 0x0000ff00));
 
- 				inputptr += 2;
 
- 			}
 
- #else
 
- 			while (cnt--) {
 
- 				*(optr++) = (u16_t)((*(inputptr) >> 16 & 0x0000ff00) | (*(inputptr + 1) >> 24 & 0x000000ff));
 
- 				inputptr += 2;
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- #endif
 
- 	case S16_LE:
 
- 		{
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt--) {
 
- 					*(optr++) = (*(inputptr) >> 16 & 0x0000ffff) | (*(inputptr + 1) & 0xffff0000);
 
- 					inputptr += 2;
 
- 				}
 
- 			} else {
 
- 				while (cnt--) {
 
- 					*(optr++) =  (gain(gainL, *(inputptr)) >> 16 & 0x0000ffff) | (gain(gainR, *(inputptr+1)) & 0xffff0000);
 
- 					inputptr += 2;
 
- 				}
 
- 			}
 
- #else
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt--) {
 
- 					s32_t lsample = *(inputptr++);
 
- 					s32_t rsample = *(inputptr++);
 
- 					*(optr++) = 
 
- 						(lsample & 0x00ff0000) << 8 | (lsample & 0xff000000) >> 8 |
 
- 						(rsample & 0x00ff0000) >> 8 | (rsample & 0xff000000) >> 24;
 
- 				}
 
- 			} else {
 
- 				while (cnt--) {
 
- 					s32_t lsample = gain(gainL, *(inputptr++));
 
- 					s32_t rsample = gain(gainR, *(inputptr++));
 
- 					*(optr++) = 
 
- 						(lsample & 0x00ff0000) << 8 | (lsample & 0xff000000) >> 8 |
 
- 						(rsample & 0x00ff0000) >> 8 | (rsample & 0xff000000) >> 24;
 
- 				}
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	case S24_LE: 
 
- 		{
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt--) {
 
- 					*(optr++) = *(inputptr++) >> 8;
 
- 					*(optr++) = *(inputptr++) >> 8;
 
- 				}
 
- 			} else {
 
- 				while (cnt--) {
 
- 					*(optr++) = gain(gainL, *(inputptr++)) >> 8;
 
- 					*(optr++) = gain(gainR, *(inputptr++)) >> 8;
 
- 				}
 
- 			}
 
- #else
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt--) {
 
- 					s32_t lsample = *(inputptr++);
 
- 					s32_t rsample = *(inputptr++);
 
- 					*(optr++) = 
 
- 						(lsample & 0xff000000) >> 16 | (lsample & 0x00ff0000) | (lsample & 0x0000ff00 << 16);
 
- 					*(optr++) = 
 
- 						(rsample & 0xff000000) >> 16 | (rsample & 0x00ff0000) | (rsample & 0x0000ff00 << 16);
 
- 				}
 
- 			} else {
 
- 				while (cnt--) {
 
- 					s32_t lsample = gain(gainL, *(inputptr++));
 
- 					s32_t rsample = gain(gainR, *(inputptr++));
 
- 					*(optr++) = 
 
- 						(lsample & 0xff000000) >> 16 | (lsample & 0x00ff0000) | (lsample & 0x0000ff00 << 16);
 
- 					*(optr++) = 
 
- 						(rsample & 0xff000000) >> 16 | (rsample & 0x00ff0000) | (rsample & 0x0000ff00 << 16);
 
- 				}
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	case S24_3LE:
 
- 		{
 
- 			u8_t *optr = (u8_t *)(void *)outputptr;
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt) {
 
- 					// attempt to do 32 bit memory accesses - move 2 frames at once: 16 bytes -> 12 bytes
 
- 					// falls through to exception case when not aligned or if less than 2 frames to move
 
- 					if (((uintptr_t)optr & 0x3) == 0 && cnt >= 2) {
 
- 						u32_t *o_ptr = (u32_t *)(void *)optr;
 
- 						while (cnt >= 2) {
 
- 							s32_t l1 = *(inputptr++); s32_t r1 = *(inputptr++);
 
- 							s32_t l2 = *(inputptr++); s32_t r2 = *(inputptr++);
 
- #if SL_LITTLE_ENDIAN
 
- 							*(o_ptr++) = (l1 & 0xffffff00) >>  8 | (r1 & 0x0000ff00) << 16;
 
- 							*(o_ptr++) = (r1 & 0xffff0000) >> 16 | (l2 & 0x00ffff00) <<  8;
 
- 							*(o_ptr++) = (l2 & 0xff000000) >> 24 | (r2 & 0xffffff00);
 
- #else
 
- 							*(o_ptr++) = (l1 & 0x0000ff00) << 16 | (l1 & 0x00ff0000) | (l1 & 0xff000000) >> 16 |
 
- 								(r1 & 0x0000ff00) >> 8; 
 
- 							*(o_ptr++) = (r1 & 0x00ff0000) <<  8 | (r1 & 0xff000000) >> 8 | (l2 & 0x0000ff00) |
 
- 								(l2 & 0x00ff0000) >> 16;
 
- 							*(o_ptr++) = (l2 & 0xff000000) | (r2 & 0x0000ff00) << 8 | (r2 & 0x00ff0000) >> 8 |
 
- 								(r2 & 0xff000000) >> 24;
 
- #endif
 
- 							optr += 12;
 
- 							cnt  -=  2;
 
- 						}
 
- 					} else {
 
- 						s32_t lsample = *(inputptr++);
 
- 						s32_t rsample = *(inputptr++);
 
- 						*(optr++) = (lsample & 0x0000ff00) >>  8;
 
- 						*(optr++) = (lsample & 0x00ff0000) >> 16;
 
- 						*(optr++) = (lsample & 0xff000000) >> 24;
 
- 						*(optr++) = (rsample & 0x0000ff00) >>  8;
 
- 						*(optr++) = (rsample & 0x00ff0000) >> 16;
 
- 						*(optr++) = (rsample & 0xff000000) >> 24;
 
- 						cnt--;
 
- 					}
 
- 				}
 
- 			} else {
 
- 				while (cnt) {
 
- 					// attempt to do 32 bit memory accesses - move 2 frames at once: 16 bytes -> 12 bytes
 
- 					// falls through to exception case when not aligned or if less than 2 frames to move
 
- 					if (((uintptr_t)optr & 0x3) == 0 && cnt >= 2) {
 
- 						u32_t *o_ptr = (u32_t *)(void *)optr;
 
- 						while (cnt >= 2) {
 
- 							s32_t l1 = gain(gainL, *(inputptr++)); s32_t r1 = gain(gainR, *(inputptr++));
 
- 							s32_t l2 = gain(gainL, *(inputptr++)); s32_t r2 = gain(gainR, *(inputptr++));
 
- #if SL_LITTLE_ENDIAN
 
- 							*(o_ptr++) = (l1 & 0xffffff00) >>  8 | (r1 & 0x0000ff00) << 16;
 
- 							*(o_ptr++) = (r1 & 0xffff0000) >> 16 | (l2 & 0x00ffff00) <<  8;
 
- 							*(o_ptr++) = (l2 & 0xff000000) >> 24 | (r2 & 0xffffff00);
 
- #else
 
- 							*(o_ptr++) = (l1 & 0x0000ff00) << 16 | (l1 & 0x00ff0000) | (l1 & 0xff000000) >> 16 |
 
- 								(r1 & 0x0000ff00) >> 8; 
 
- 							*(o_ptr++) = (r1 & 0x00ff0000) <<  8 | (r1 & 0xff000000) >> 8 | (l2 & 0x0000ff00) |
 
- 								(l2 & 0x00ff0000) >> 16;
 
- 							*(o_ptr++) = (l2 & 0xff000000) | (r2 & 0x0000ff00) << 8 | (r2 & 0x00ff0000) >> 8 |
 
- 								(r2 & 0xff000000) >> 24;
 
- #endif
 
- 							optr += 12;
 
- 							cnt  -=  2;
 
- 						}
 
- 					} else {
 
- 						s32_t lsample = gain(gainL, *(inputptr++));
 
- 						s32_t rsample = gain(gainR, *(inputptr++));
 
- 						*(optr++) = (lsample & 0x0000ff00) >>  8;
 
- 						*(optr++) = (lsample & 0x00ff0000) >> 16;
 
- 						*(optr++) = (lsample & 0xff000000) >> 24;
 
- 						*(optr++) = (rsample & 0x0000ff00) >>  8;
 
- 						*(optr++) = (rsample & 0x00ff0000) >> 16;
 
- 						*(optr++) = (rsample & 0xff000000) >> 24;
 
- 						cnt--;
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 		break;
 
- 	case S32_LE:
 
- 		{
 
- 			u32_t *optr = (u32_t *)(void *)outputptr;
 
- #if SL_LITTLE_ENDIAN
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				memcpy(outputptr, inputptr, cnt * BYTES_PER_FRAME);
 
- 			} else {
 
- 				while (cnt--) {
 
- 					*(optr++) = gain(gainL, *(inputptr++));
 
- 					*(optr++) = gain(gainR, *(inputptr++));
 
- 				}
 
- 			}
 
- #else
 
- 			if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
 
- 				while (cnt--) {
 
- 					s32_t lsample = *(inputptr++);
 
- 					s32_t rsample = *(inputptr++);
 
- 					*(optr++) = 
 
- 						(lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
 
- 						(lsample & 0x0000ff00) << 8  | (lsample & 0x000000ff) << 24;
 
- 					*(optr++) = 
 
- 						(rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
 
- 						(rsample & 0x0000ff00) << 8  | (rsample & 0x000000ff) << 24;
 
- 				}
 
- 			} else {
 
- 				while (cnt--) {
 
- 					s32_t lsample = gain(gainL, *(inputptr++));
 
- 					s32_t rsample = gain(gainR, *(inputptr++));
 
- 					*(optr++) = 
 
- 						(lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
 
- 						(lsample & 0x0000ff00) << 8  | (lsample & 0x000000ff) << 24;
 
- 					*(optr++) = 
 
- 						(rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
 
- 						(rsample & 0x0000ff00) << 8  | (rsample & 0x000000ff) << 24;
 
- 				}
 
- 			}
 
- #endif
 
- 		}
 
- 		break;
 
- 	default:
 
- 		break;
 
- 	}
 
- }
 
- #if !WIN
 
- inline 
 
- #endif
 
- void _apply_cross(struct buffer *outputbuf, frames_t out_frames, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
 
- 	ISAMPLE_T *ptr = (ISAMPLE_T *)(void *)outputbuf->readp;
 
- 	frames_t count = out_frames * 2;
 
- 	while (count--) {
 
- 		if (*cross_ptr > (ISAMPLE_T *)outputbuf->wrap) {
 
- 			*cross_ptr -= outputbuf->size / BYTES_PER_FRAME * 2;
 
- 		}
 
- 		*ptr = gain(cross_gain_out, *ptr) + gain(cross_gain_in, **cross_ptr);
 
- 		ptr++; (*cross_ptr)++;
 
- 	}
 
- }
 
- #if !WIN
 
- inline 
 
- #endif
 
- void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR, u8_t flags) {
 
- 	if (gainL == FIXED_ONE && gainR == FIXED_ONE && !(flags & (MONO_LEFT | MONO_RIGHT))) {
 
- 		return;
 
- 	} else if ((flags & MONO_LEFT) && (flags & MONO_RIGHT)) {
 
- 		ISAMPLE_T *ptrL = (ISAMPLE_T *)(void *)outputbuf->readp;
 
- 		ISAMPLE_T *ptrR = (ISAMPLE_T *)(void *)outputbuf->readp + 1;
 
- 		while (count--) {
 
- 			*ptrL = *ptrR = (gain(gainL, *ptrL) + gain(gainR, *ptrR)) / 2;
 
- 			ptrL += 2; ptrR += 2;
 
- 		}
 
- 	} else if (flags & MONO_RIGHT) {
 
- 		ISAMPLE_T *ptr = (ISAMPLE_T *)(void *)outputbuf->readp + 1;
 
- 		while (count--) {
 
- 			*(ptr - 1) = *ptr = gain(gainR, *ptr);
 
- 			ptr += 2;
 
- 		}
 
- 	} else if (flags & MONO_LEFT) {
 
- 		ISAMPLE_T *ptr = (ISAMPLE_T *)(void *)outputbuf->readp;
 
- 		while (count--) {
 
- 			*(ptr + 1) = *ptr = gain(gainL, *ptr);
 
- 			ptr += 2;
 
- 		}
 
- 	} else {
 
- 	   	ISAMPLE_T *ptrL = (ISAMPLE_T *)(void *)outputbuf->readp;
 
- 		ISAMPLE_T *ptrR = (ISAMPLE_T *)(void *)outputbuf->readp + 1;
 
- 		while (count--) {
 
- 			*ptrL = gain(gainL, *ptrL);
 
- 			*ptrR = gain(gainR, *ptrR);
 
- 			ptrL += 2; ptrR += 2;
 
- 		}
 
- 	}
 
- }
 
 
  |