Part of Slepp's ProjectsPastebinTURLImagebinFilebin
Feedback -- English French German Japanese
Create Upload Newest Tools Donate
Sign In | Create Account

DSP plugin examples
Wednesday, August 8th, 2007 at 8:34:44pm UTC 

  1. /***************************************************************************
  2. *             __________               __   ___.
  3. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
  4. *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
  5. *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  6. *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  7. *                     \/            \/     \/    \/            \/
  8. * $Id:$
  9. *
  10. * Copyright (C) 2006 Michael Sevakis
  11. *
  12. * All files in this archive are subject to the GNU General Public License.
  13. * See the file COPYING in the source tree root for full license agreement.
  14. *
  15. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  16. * KIND, either express or implied.
  17. *
  18. ****************************************************************************/
  19. #include "plugin.h"
  20.  
  21. /* Button mapping */
  22. #if CONFIG_KEYPAD == IRIVER_H100_PAD
  23. #define EFFECT_QUIT BUTTON_ON
  24. #elif CONFIG_KEYPAD == IAUDIO_X5_PAD
  25. #define EFFECT_QUIT BUTTON_POWER
  26. #endif
  27.  
  28. PLUGIN_HEADER
  29. PLUGIN_IRAM_DECLARE
  30.  
  31. static struct plugin_api* rb;
  32.  
  33. static int queue_size;
  34. /* Imporant to leave enough room behind effect_index to allow for delays like screen updates */
  35. static volatile int wr_index = 4;
  36. static volatile int rd_index = 0;
  37. static int effect_index      = 4; /* one ahead to account for preincrement of wr_index */
  38.  
  39. static unsigned long effect_thread_stack[DEFAULT_STACK_SIZE] IBSS_ATTR;
  40. static bool stop_effect = false;
  41.  
  42. #define CHUNK_SAMPLES   128
  43. #define CHUNK_SIZE      (CHUNK_SAMPLES*4)
  44. #define NUM_CHUNKS      8 /* power of 2 */
  45. #define CHUNK_MASK      (NUM_CHUNKS-1)
  46. #define NEXT_CHUNK(x)   (((x) + 1) & CHUNK_MASK)
  47.  
  48. typedef int32_t (* buffer_t)[CHUNK_SAMPLES];
  49. buffer_t __attribute__((aligned(16))) queue;
  50.  
  51. /* Effect data */
  52. struct lfo {
  53.         int32_t phase, delta;
  54. };
  55.  
  56. struct delay {
  57.         size_t writepos;
  58.         size_t mask;
  59.         int32_t delay;
  60.         int16_t *delayline;
  61. };
  62.  
  63. struct lfo trilfo = { 0, 0xffffffff/44100/5};
  64. int16_t delayline_l[65536], delayline_r[65536];
  65. struct delay delay1 = { 0, 0xffff, (10000 << 15) + 0x1fff, delayline_l };
  66.  
  67. static inline int32_t saw_lfo(struct lfo *l)
  68. {
  69.     int32_t ret = l->phase;
  70.     l->phase += l->delta;
  71.     return ret;
  72. }
  73.  
  74. static inline int32_t tri_lfo(struct lfo *l)
  75. {
  76.     int32_t ret = (abs(l->phase + 0x3fffffff) - 0x3fffffff) << 1;
  77.     l->phase += l->delta;
  78.     return ret;
  79. }
  80.  
  81. static inline int32_t par_lfo(struct lfo *l)
  82. {
  83.     int32_t shift_phase = l->phase >> 16;
  84.     int32_t ret = 8*shift_phase*((1 << 15) - abs(shift_phase));
  85.     l->phase += l->delta;
  86.     return ret;
  87. }
  88.  
  89. static void delay_process(int16_t *data, struct delay *d, int num) ICODE_ATTR;
  90. static void delay_process(int16_t *data, struct delay *d, int num)
  91. {
  92.         int i;
  93.         size_t mask = d->mask;
  94.     size_t writepos = d->writepos;
  95.  
  96.         for (i = 0; i < num; ++i) {
  97.                 d->delay = (441 << 15) + par_lfo(&trilfo)/1600;
  98.                 size_t r = writepos - (d->delay >> 15);
  99.                 int32_t frac = 0x8000 - (d->delay & 0x7fff);
  100.  
  101.                 const int32_t xm1 = d->delayline[(r - 1) & mask];
  102.                 const int32_t x0 = d->delayline[r & mask];
  103.                 const int32_t xp1 = d->delayline[(r + 1) & mask];
  104.                 const int32_t xp2 = d->delayline[(r + 2) & mask];
  105.        
  106.                 const int32_t c = (xp1 - xm1)/2;
  107.         const int32_t v = x0 - xp1;
  108.         const int32_t w = c + v;
  109.         const int32_t a = w + v + (xp2 - x0)/2;
  110.         const int32_t b = w + a;
  111.            
  112.                 int32_t output = (((((a*frac >> 15) - b)*frac >> 15) + c)*frac >> 15) + x0;
  113.                 int32_t input = *data;
  114.                 d->delayline[writepos] = input + output*2/10;
  115.                 *data++ = (input + output)/2;
  116.                 *data++ = (input + output)/2;
  117.                 writepos = (writepos + 1) & mask;
  118.         }
  119.     d->writepos = writepos;
  120. }
  121.  
  122. static void play_callback(unsigned char **start, size_t *size) ICODE_ATTR;
  123. static void play_callback(unsigned char **start, size_t *size)
  124. {
  125.     rd_index = NEXT_CHUNK(rd_index);
  126.     *start = (unsigned char *)queue[rd_index];
  127.     *size  = CHUNK_SIZE;
  128. }
  129.  
  130. static int record_callback(int status) ICODE_ATTR;
  131. static int record_callback(int status)
  132. {
  133.     wr_index = NEXT_CHUNK(wr_index);
  134.     rb->pcm_record_more(queue[wr_index], CHUNK_SIZE);
  135.     return 0;
  136.     (void)status;
  137. }
  138.  
  139. static void effect_thread(void) ICODE_ATTR;
  140. static void effect_thread(void)
  141. {
  142.     int y = 0;
  143.     while (!stop_effect)
  144.     {
  145.         /* Wait for at least one chunk of data available */
  146.         while (wr_index == effect_index)
  147.         {
  148.             rb->yield();
  149.             if (stop_effect)
  150.                 goto effect_done;
  151.         }
  152.  
  153.         do
  154.         {
  155.             int16_t *ptr = (int16_t *)queue[effect_index];
  156.             delay_process(ptr, &delay1, CHUNK_SAMPLES);
  157.            
  158.             effect_index  = NEXT_CHUNK(effect_index);
  159.  
  160.             if (++y >= 8)
  161.             {
  162.                 rb->yield();
  163.                 y = 0;
  164.             }
  165.         }
  166.         while (effect_index != wr_index);
  167.     }
  168.  
  169. effect_done:
  170.     /* main thread waits for this to turn false again */
  171.     stop_effect = false;
  172.     rb->remove_thread(NULL);
  173. }
  174.  
  175. /* this is the plugin entry point */
  176. enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
  177. {
  178.     PLUGIN_IRAM_INIT(api);
  179.  
  180.     rb = api;
  181.  
  182.     queue = (buffer_t)rb->plugin_get_audio_buffer(&queue_size);
  183.     rb->memset(queue, 0, CHUNK_SIZE*NUM_CHUNKS);
  184.     rb->memset(delayline_l, 0, sizeof(delayline_l));
  185.  
  186.     rb->pcm_init_recording();
  187.     rb->pcm_set_frequency(SAMPR_44);
  188.     rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
  189.     rb->rec_set_source(AUDIO_SRC_LINEIN, SRCF_RECORDING);
  190.     rb->pcm_apply_settings(true);
  191.  
  192.     rb->cpu_boost(true);
  193.  
  194.     rb->pcm_record_data(record_callback, queue[wr_index], CHUNK_SIZE);
  195.     rb->pcm_play_data(play_callback, NULL, 0);
  196.  
  197.     rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME));
  198.     rb->audio_set_recording_gain(rb->sound_default(SOUND_LEFT_GAIN) + 10,
  199.             rb->sound_default(SOUND_RIGHT_GAIN) + 10, AUDIO_GAIN_LINEIN);
  200.  
  201.     /* Start a thread for processing the audio */
  202.     rb->create_thread(effect_thread, effect_thread_stack,
  203.                       sizeof(effect_thread_stack), "effect thread",
  204.                       PRIORITY_RECORDING);
  205.  
  206.     while (rb->button_get_w_tmo(HZ/10) != EFFECT_QUIT)
  207.     {
  208.         char buf[32];
  209.         rb->snprintf(buf, ARRAYLEN(buf), "rd: %d ef:%d wr: %d",
  210.                      rd_index, effect_index, wr_index);
  211.         rb->lcd_puts(0, 0, buf);
  212.         rb->yield();
  213.         rb->lcd_update();
  214.         rb->yield();
  215.     }
  216.  
  217.     /* stop effect thread - it will remove itself */
  218.     stop_effect = true;
  219.     while (stop_effect)
  220.         rb->yield();
  221.  
  222.     rb->pcm_play_stop();
  223.     rb->pcm_stop_recording();
  224.     rb->pcm_close_recording();
  225.  
  226.     rb->cpu_boost(false);
  227.  
  228.     rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
  229.     rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
  230.     rb->rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
  231.     rb->pcm_apply_settings(true);
  232.  
  233.     return PLUGIN_OK;
  234.     (void)parameter;
  235. }

Update the Post

Either update this post and resubmit it with changes, or make a new post.

You may also comment on this post.

update paste below
details of the post (optional)

Note: Only the paste content is required, though the following information can be useful to others.

Save name / title?

(space separated, optional)



Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.

comments powered by Disqus
worth-right
worth-right
worth-right