⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 peakmeter.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 2 页
字号:
 * @param int range_max - Specifies the upper value of the range.  *                        Pass a value dBfs * 100 when dbfs is set to true. *                        Pass a percent value when dbfs is set to false. */void peak_meter_init_range( bool dbfs, int range_min, int range_max) {    peak_meter_use_dbfs = dbfs;    peak_meter_set_min(range_min);    peak_meter_set_max(range_max);}/** * Initialize the peak meter with all relevant values concerning times. * @param int release - Set the maximum amount of pixels the meter is allowed *                      to decrease with each redraw * @param int hold - Select the time preset for the time the peak indicator  *                   is reset after a peak occurred. The preset values are  *                   stored in max_time_out. * @param int clip_hold - Select the time preset for the time the peak  *                        indicator is reset after a peak occurred. The preset  *                        values are stored in clip_time_out. */void peak_meter_init_times(int release, int hold, int clip_hold) {    peak_meter_hold = hold;    peak_meter_release = release;    peak_meter_clip_hold = clip_hold;}/** * Set the source of the peak meter to playback or to  * record. * @param: bool playback - If true playback peak meter is used. *         If false recording peak meter is used. */void peak_meter_playback(bool playback) {#ifdef SIMULATOR    (void)playback;#else    if (playback) {        peak_meter_src_l = MAS_REG_DQPEAK_L;        peak_meter_src_r = MAS_REG_DQPEAK_R;    } else {        peak_meter_src_l = MAS_REG_QPEAK_L;        peak_meter_src_r = MAS_REG_QPEAK_R;    }#endif}/** * Reads peak values from the MAS, and detects clips. The  * values are stored in peak_meter_l peak_meter_r for later  * evauluation. Consecutive calls to peak_meter_peek detect  * that ocurred. This function could be used by a thread for * busy reading the MAS. */inline void peak_meter_peek(void) {#ifdef SIMULATOR    int left = 8000;    int right = 9000;#else   /* read the peak values */    int left  = mas_codec_readreg(peak_meter_src_l);    int right = mas_codec_readreg(peak_meter_src_r);#endif    /* check for clips       An clip is assumed when two consecutive readouts       of the volume are at full scale. This is proven       to be inaccurate in both ways: it may detect clips       when no clip occurred and it may fail to detect       a real clip. */    if ((left  == peak_meter_l) &&         (left  == MAX_PEAK - 1)) {        peak_meter_l_clip = true;        peak_meter_clip_timeout_l =             current_tick + clip_time_out[peak_meter_clip_hold];    }    if ((right == peak_meter_r) &&         (right == MAX_PEAK - 1)) {        peak_meter_r_clip = true;        peak_meter_clip_timeout_r =             current_tick + clip_time_out[peak_meter_clip_hold];    }    /* peaks are searched -> we have to find the maximum. When       many calls of peak_meter_peek the maximum value will be       stored in peak_meter_x. This maximum is reset by the       functions peak_meter_read_x. */    peak_meter_l = MAX(peak_meter_l, left);    peak_meter_r = MAX(peak_meter_r, right);#ifdef PM_DEBUG    peek_calls++;#endif}/** * The thread function for the peak meter calls peak_meter_peek  * to reas out the mas and find maxima, clips, etc. No display * is performed. *//*void peak_meter_thread(void) {    sleep(5000);    while (1) {        if (peak_meter_enabled && peak_meter_use_thread){            peak_meter_peek();        }        yield();    }}*//** * Creates the peak meter thread  *//*void peak_meter_init(void) {    create_thread(        peak_meter_thread,         peak_meter_stack,         sizeof peak_meter_stack,         "peakmeter");}*//** * Reads out the peak volume of the left channel. * @return int - The maximum value that has been detected * since the last call of peak_meter_read_l. The value * is in the range 0 <= value < MAX_PEAK. */static int peak_meter_read_l (void) {    /* peak_meter_l contains the maximum of       all peak values that were read by peak_meter_peek        since the last call of peak_meter_read_r */    int retval = peak_meter_l;#ifdef PM_DEBUG    peek_calls = 0;#endif#ifdef SIMULATOR    peak_meter_l = 8000;#else    /* reset peak_meter_l so that subsequent calls of       peak_meter_peek doesn't get fooled by an old       maximum value */    peak_meter_l = mas_codec_readreg(peak_meter_src_l);#endif    return retval;}/** * Reads out the peak volume of the right channel. * @return int - The maximum value that has been detected * since the last call of peak_meter_read_l. The value * is in the range 0 <= value < MAX_PEAK. */static int peak_meter_read_r (void) {    /* peak_meter_r contains the maximum of       all peak values that were read by peak_meter_peek        since the last call of peak_meter_read_r */    int retval = peak_meter_r;#ifdef PM_DEBUG    peek_calls = 0;#endif#ifdef SIMULATOR    peak_meter_l = 8000;#else    /* reset peak_meter_r so that subsequent calls of       peak_meter_peek doesn't get fooled by an old       maximum value */    peak_meter_r = mas_codec_readreg(peak_meter_src_r);#endif    return retval;}/** * Reset the detected clips. This method is for * use by the user interface. * @param int unused - This parameter was added to * make the function compatible with set_int */void peak_meter_set_clip_hold(int time) {    peak_meter_clip_eternal = false;    if (time <= 0) {        peak_meter_l_clip = false;        peak_meter_r_clip = false;        peak_meter_clip_eternal = true;    }}/** * Scales a peak value as read from the MAS to the range of meterwidth. * The scaling is performed according to the scaling method (dBfs / linear) * and the range (peak_meter_range_min .. peak_meter_range_max). * @param unsigned short val - The volume value. Range: 0 <= val < MAX_PEAK * @param int meterwidht - The widht of the meter in pixel * @return unsigned short - A value 0 <= return value <= meterwidth */unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){    int retval;    if (val <= peak_meter_range_min) {        return 0;    }    if (val >= peak_meter_range_max) {        return meterwidth;    }    retval = val;    /* different scaling is used for dBfs and linear percent */    if (peak_meter_use_dbfs) {        /* scale the samples dBfs */        retval  = (calc_db(retval) - db_min) * meterwidth / db_range;    }    /* Scale for linear percent display */    else    {        /* scale the samples */        retval  = ((retval - peak_meter_range_min) * meterwidth)                   / peak_meter_range;    }    return retval;}/** * Draws a peak meter in the specified size at the specified position. * @param int x - The x coordinate.  *                Make sure that 0 <= x and x + width < LCD_WIDTH * @param int y - The y coordinate.  *                Make sure that 0 <= y and y + height < LCD_HEIGHT * @param int width - The width of the peak meter. Note that for display *                    of clips a 3 pixel wide area is used -> *                    width > 3 * @param int height - The height of the peak meter. height > 3 */void peak_meter_draw(int x, int y, int width, int height) {    int left = 0, right = 0;    static int last_left = 0, last_right = 0;    int meterwidth = width - 3;    int i;#ifdef PM_DEBUG    static long pm_tick = 0;    int tmp = peek_calls;#endif    /* if disabled only draw the peak meter */    if (peak_meter_enabled) {        /* read the volume info from MAS */        left  = peak_meter_read_l();         right = peak_meter_read_r();         /*peak_meter_peek();*/        /* scale the samples dBfs */        left  = peak_meter_scale_value(left, meterwidth);        right = peak_meter_scale_value(right, meterwidth);            /* if the scale has changed -> recalculate the scale            (The scale becomes invalid when the range changed.) */        if (!db_scale_valid){            if (peak_meter_use_dbfs) {                db_scale_count = DB_SCALE_SRC_VALUES_SIZE;                for (i = 0; i < db_scale_count; i++){                    /* find the real x-coords for predefined interesting                       dBfs values. These only are recalculated when the                       scaling of the meter changed. */                        db_scale_lcd_coord[i] =                             peak_meter_scale_value(                                db_scale_src_values[i],                                 meterwidth - 1);                }             }            /* when scaling linear we simly make 10% steps */            else {                db_scale_count = 10;                for (i = 0; i < db_scale_count; i++) {                    db_scale_lcd_coord[i] =                         (i * (MAX_PEAK / 10) - peak_meter_range_min) *                        meterwidth / peak_meter_range;                }            }            /* mark scale valid to avoid recalculating dBfs values               of the scale. */            db_scale_valid = true;        }        /* apply release */        left  = MAX(left , last_left  - peak_meter_release);        right = MAX(right, last_right - peak_meter_release);        /* reset max values after timeout */        if (TIME_AFTER(current_tick, peak_meter_timeout_l)){            peak_meter_max_l = 0;        }        if (TIME_AFTER(current_tick, peak_meter_timeout_r)){            peak_meter_max_r = 0;        }        if (!peak_meter_clip_eternal) {            if (peak_meter_l_clip &&                 TIME_AFTER(current_tick, peak_meter_clip_timeout_l)){                peak_meter_l_clip = false;            }            if (peak_meter_r_clip &&                 TIME_AFTER(current_tick, peak_meter_clip_timeout_r)){                peak_meter_r_clip = false;            }        }        /* check for new max values */        if (left > peak_meter_max_l) {            peak_meter_max_l = left - 1;            peak_meter_timeout_l =                 current_tick + max_time_out[peak_meter_hold];        }        if (right > peak_meter_max_r) {            peak_meter_max_r = right - 1;            peak_meter_timeout_r =                 current_tick + max_time_out[peak_meter_hold];        }    }    /* draw the peak meter */    lcd_clearrect(x, y, width, height);    /* draw left */    lcd_fillrect (x, y, left, height / 2 - 2 );    if (peak_meter_max_l > 0) {        lcd_drawline(x + peak_meter_max_l, y,                      x + peak_meter_max_l, y + height / 2 - 2 );    }    if (peak_meter_l_clip) {        lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1);    }    /* draw right */    lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2);    if (peak_meter_max_r > 0) {        lcd_drawline( x + peak_meter_max_r, y + height / 2,                       x + peak_meter_max_r, y + height - 2);    }    if (peak_meter_r_clip) {        lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1);    }    /* draw scale end */    lcd_drawline(x + meterwidth, y,                 x + meterwidth, y + height - 2);        /* draw dots for scale marks */    for (i = 0; i < db_scale_count; i++) {        /* The x-coordinates of interesting scale mark points            have been calculated before */        lcd_invertpixel(db_scale_lcd_coord[i], y + height / 2 - 1);    }#ifdef PM_DEBUG    /* display a bar to show how many calls to peak_meter_peek        have ocurred since the last display */    lcd_invertrect(x, y, tmp, 3);    if (tmp < PEEKS_PER_DRAW_SIZE) {        peeks_per_redraw[tmp]++;    }    tmp = current_tick - pm_tick;    if (tmp < TICKS_PER_DRAW_SIZE ){        ticks_per_redraw[tmp] ++;    }    /* display a bar to show how many ticks have passed since        the last redraw */    lcd_invertrect(x, y + height / 2, current_tick - pm_tick, 2);    pm_tick = current_tick;#endif    last_left = left;    last_right = right;}#ifdef PM_DEBUGstatic void peak_meter_clear_histogram(void) {    int i = 0;    for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) {        ticks_per_redraw[i] = (unsigned int)0;    }    for (i = 0; i < PEEKS_PER_DRAW_SIZE; i++) {        peeks_per_redraw[i] = (unsigned int)0;    }}bool peak_meter_histogram(void) {    int i;    int btn = BUTTON_NONE;    while ((btn & BUTTON_OFF) != BUTTON_OFF )    {        unsigned int max = 0;        int y = 0;        int x = 0;        lcd_clear_display();        for (i = 0; i < PEEKS_PER_DRAW_SIZE; i++) {            max = MAX(max, peeks_per_redraw[i]);        }        for (i = 0; i < PEEKS_PER_DRAW_SIZE; i++) {            x = peeks_per_redraw[i] * (LCD_WIDTH - 1)/ max;            lcd_drawline(0, y + i, x, y + i);        }        y = PEEKS_PER_DRAW_SIZE + 1;        max = 0;        for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) {            max = MAX(max, ticks_per_redraw[i]);        }        for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) {            x = ticks_per_redraw[i] * (LCD_WIDTH - 1)/ max;            lcd_drawline(0, y + i, x, y + i);        }        lcd_update();                btn = button_get(true);        if (btn == BUTTON_PLAY) {            peak_meter_clear_histogram();        }    }    return false;}#endif 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -