A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 103 lines 3.7 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (c) 2011 Michael Sevakis 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#include "config.h" 22#include "system.h" 23#include "settings.h" 24#include "pcm.h" 25#include "pcm_mixer.h" 26#include "misc.h" 27#include "fixedpoint.h" 28 29/** Beep generation, CPU optimized **/ 30#include "asm/beep.c" 31 32static uint32_t beep_phase; /* Phase of square wave generator */ 33static uint32_t beep_step; /* Step of square wave generator on each sample */ 34#ifdef BEEP_GENERIC 35static int16_t beep_amplitude; /* Amplitude of square wave generator */ 36#else 37/* Optimized routines do XOR with phase sign bit in both channels at once */ 38static uint32_t beep_amplitude; /* Amplitude of square wave generator */ 39#endif 40static int beep_count; /* Number of samples remaining to generate */ 41 42#define BEEP_COUNT(fs, duration) ((fs) / 1000 * (duration)) 43 44/* Reserve enough static space for keyclick to fit in worst case */ 45#define BEEP_BUF_COUNT BEEP_COUNT(PLAY_SAMPR_MAX, KEYCLICK_DURATION) 46static int16_t beep_buf[BEEP_BUF_COUNT*2] IBSS_ATTR __attribute__((aligned(4))); 47 48/* Callback to generate the beep frames - also don't want inlining of 49 call below in beep_play */ 50static void __attribute__((noinline)) 51beep_get_more(const void **start, size_t *size) 52{ 53 int count = beep_count; 54 55 if (count > 0) 56 { 57 count = MIN(count, BEEP_BUF_COUNT); 58 beep_count -= count; 59 *start = beep_buf; 60 *size = count * 2 * sizeof (int16_t); 61 beep_generate((void *)beep_buf, count, &beep_phase, 62 beep_step, beep_amplitude); 63 } 64} 65 66/* Generates a constant square wave sound with a given frequency in Hertz for 67 a duration in milliseconds */ 68void beep_play(unsigned int frequency, unsigned int duration, 69 unsigned int amplitude) 70{ 71 mixer_channel_stop(PCM_MIXER_CHAN_BEEP); 72 73 if (frequency == 0 || duration == 0 || amplitude == 0) 74 return; 75 76 if (amplitude > INT16_MAX) 77 amplitude = INT16_MAX; 78 79 /* Setup the parameters for the square wave generator */ 80 uint32_t fout = mixer_get_frequency(); 81 beep_phase = 0; 82 beep_step = fp_div(frequency, fout, 32); 83 beep_count = BEEP_COUNT(fout, duration); 84 85#ifdef BEEP_GENERIC 86 beep_amplitude = amplitude; 87#else 88 /* Optimized routines do XOR with phase sign bit in both channels at once */ 89 beep_amplitude = amplitude | (amplitude << 16); /* Word:|AMP16|AMP16| */ 90#endif 91 92 /* If it fits - avoid cb overhead */ 93 const void *start; 94 size_t size; 95 96 /* Generate first frame here */ 97 beep_get_more(&start, &size); 98 99 mixer_channel_set_amplitude(PCM_MIXER_CHAN_BEEP, MIX_AMP_UNITY); 100 mixer_channel_play_data(PCM_MIXER_CHAN_BEEP, 101 beep_count ? beep_get_more : NULL, 102 start, size); 103}