https://bitbucket.org/daniel_fort/magic-lantern
Raw File
Tip revision: 128459811ce1ff28aea3f9f20971b3d059e76738 authored by alex@thinkpad on 13 October 2012, 17:05:35 UTC
5DC: Added a small joke on "don't click me" :)
Tip revision: 1284598
audio-ak.c
/** \file
 * Onscreen audio meters
 */
/*
 * Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
 * 
 * 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 2
 * 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, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "dryos.h"
#include "bmp.h"
#include "config.h"
#include "property.h"
#include "menu.h"
#include "gui.h"
#include "audio-common.c"

CONFIG_INT( "audio.dgain.l",    dgain_l,        0 );
CONFIG_INT( "audio.dgain.r",    dgain_r,        0 );
CONFIG_INT( "audio.mgain",      mgain,          4 );
CONFIG_INT( "audio.mic-power",  mic_power,      1 );
CONFIG_INT( "audio.o2gain",     o2gain,         0 );
//CONFIG_INT( "audio.mic-in",   mic_in,         0 ); // not used any more?

int audio_meters_are_drawn()
{
    if (!SOUND_RECORDING_ENABLED && !fps_should_record_wav())
        return 0;
    return 
        (
         is_movie_mode() && cfg_draw_meters && do_draw_meters && (zebra_should_run() || get_halfshutter_pressed()) && !gui_menu_shown()
         )
        ||
        (
         gui_menu_shown() && is_menu_active("Audio") && cfg_draw_meters
         );
}


#if defined(CONFIG_500D)

static inline void
audio_ic_set_mgain(
                   unsigned             index
                   )
{
    unsigned sig1 = audio_ic_read( AUDIO_IC_SIG1 );
    unsigned sig2 = audio_ic_read( AUDIO_IC_SIG2 );
    
    // setting the bits for each possible gain setting in the 500d.
    switch (index)
        {
        case 0: // 0 dB
            sig1 &= ~(1 << 0);
            sig1 &= ~(1 << 1);
            sig1 &= ~(1 << 3);
            sig2 &= ~(1 << 5);
            break;
            
        case 1: // 3 dB
            sig1 &= ~(1 << 0);
            sig1 &= ~(1 << 1);
            sig1 |= 1 << 3;
            sig2 &= ~(1 << 5);
            break;
            
        case 2: // 6 dB
            sig1 &= ~(1 << 1);
            sig1 |= 1 << 0;
            sig1 |= 1 << 3;
            sig2 &= ~(1 << 5);
            break;
            
        case 3: // 10 dB
            sig1 &= ~(1 << 0);
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 1;
            sig2 &= ~(1 << 5);
            break;
            
        case 4: // 17 dB
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 0;
            sig1 |= 1 << 1;
            sig2 &= ~(1 << 5);
            break;
            
        case 5: // 20 dB
            sig1 &= ~(1 << 1);
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 0;            
            sig2 &= ~(1 << 5);
            break;
            
        case 6: // 23 dB
            sig1 &= ~(1 << 0);
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 1;
            sig2 |= 1 << 5;
            break;
            
        case 7: // 26 dB
            sig1 &= ~(1 << 0);
            sig1 &= ~(1 << 1);
            sig1 &= ~(1 << 3);
            sig2 |= 1 << 5;
            break;
            
        case 8: // 29 dB
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 0;
            sig1 |= 1 << 1;
            sig2 |= 1 << 5;
            break;
            
        case 9: // 32 dB
            sig1 &= ~(1 << 1);
            sig1 &= ~(1 << 3);
            sig1 |= 1 << 0;
            sig2 |= 1 << 5;
            break;
        }
    
    audio_ic_write( AUDIO_IC_SIG1 | sig1 );
    gain.sig1 = sig1;
    
    audio_ic_write( AUDIO_IC_SIG2 | sig2 );
    gain.sig2 = sig2;
}
/* <- CONFIG_500D*/
#else
static inline void
audio_ic_set_mgain(
                   unsigned             index
                   )
{
    unsigned bits = mgain_index2bits(index);
    bits &= 0x7;
    unsigned sig1 = audio_ic_read( AUDIO_IC_SIG1 );
    sig1 &= ~0x3;
    sig1 |= (bits & 1);
    sig1 |= (bits & 4) >> 1;
    audio_ic_write( AUDIO_IC_SIG1 | sig1 );
    gain.sig1 = sig1;
    
    unsigned sig2 = audio_ic_read( AUDIO_IC_SIG2 );
    sig2 &= ~(1<<5);
    sig2 |= (bits & 2) << 4;
    audio_ic_write( AUDIO_IC_SIG2 | sig2 );
    gain.sig2 = sig2;
}
#endif

#if !defined(CONFIG_500D)
//no support for anything but gain for now.
static inline void
audio_ic_set_input_volume(
                          int                   channel,
                          int                   gain
                          )
{
    unsigned cmd = audio_gain_to_cmd( gain );
    if( channel )
        cmd |= AUDIO_IC_IVL;
    else
        cmd |= AUDIO_IC_IVR;
    
    audio_ic_write( cmd );
}
#endif

int get_mic_power(int input_source)
{
    return (input_source >= 2) ? mic_power : 1;
}

static void audio_monitoring_update()
{
    #ifdef HOTPLUG_VIDEO_OUT_STATUS_ADDR
    // kill video connect/disconnect event... or not
    *(int*)HOTPLUG_VIDEO_OUT_STATUS_ADDR = audio_monitoring ? 2 : 0;
        
    if (audio_monitoring && rca_monitor)
        {
            audio_monitoring_force_display(0);
            msleep(1000);
            audio_monitoring_display_headphones_connected_or_not();
        }
    #endif
}


void
audio_configure( int force )
{
#if defined(CONFIG_5D3)
    return;
#endif

    extern int beep_playing;
    if (beep_playing && !(audio_monitoring && AUDIO_MONITORING_HEADPHONES_CONNECTED))
        return; // don't redirect wav playing to headphones if they are not connected

#ifdef CONFIG_AUDIO_REG_LOG
    audio_reg_dump( force );
    return;
#endif
#ifdef CONFIG_AUDIO_REG_BMP
    audio_reg_dump_screen();
    return;
#endif

    // redirect wav playing to headphones if they are connected
    int loopback0 = beep_playing ? 0 : loopback;
    
    int pm3[] = { 0x00, 0x05, 0x07, 0x11 }; //should this be in a header file?

    audio_set_meterlabel();
    
#ifdef CONFIG_1100D
    return;
#endif
    if( !force )
        {
            // Check for ALC configuration; do nothing if it is
            // already disabled
            if( audio_ic_read( AUDIO_IC_ALC1 ) == gain.alc1
                &&  audio_ic_read( AUDIO_IC_SIG1 ) == gain.sig1
                &&  audio_ic_read( AUDIO_IC_SIG2 ) == gain.sig2
                )
                return;
            DebugMsg( DM_AUDIO, 3, "%s: Reseting user settings", __func__ );
        }
        
    //~ static int iter=0;
    //~ bmp_printf(FONT_MED, 0, 70, "audio configure(%d)", iter++);
    
    audio_ic_write( AUDIO_IC_PM1 | 0x6D ); // power up ADC and DAC
        
#ifdef CONFIG_500D //500d only has internal mono audio :(
    int input_source = 0;
#else
    int input_source = get_input_source();
#endif
    //mic_power is forced on if input source is 0 or 1
    int mic_pow = get_mic_power(input_source);
    
    audio_ic_write( AUDIO_IC_SIG1
                    | 0x10
                    | ( mic_pow ? 0x4 : 0x0 )
                    ); // power up, no gain
    
    audio_ic_write( AUDIO_IC_SIG2
                    | 0x04 // external, no gain
                    | ( lovl & 0x3) << 0 // line output level
                    );
        
        
    
#ifdef CONFIG_500D
    audio_ic_write( AUDIO_IC_SIG4 | pm3[input_source] );
#else
    //PM3 is set according to the input choice
    audio_ic_write( AUDIO_IC_PM3 | pm3[input_source] );
#endif
    
    gain.alc1 = alc_enable ? (1<<5) : 0;
    audio_ic_write( AUDIO_IC_ALC1 | gain.alc1 ); // disable all ALC
    
#ifndef CONFIG_500D
    // Control left/right gain independently
    audio_ic_write( AUDIO_IC_MODE4 | 0x00 );
        
    audio_ic_set_input_volume( 0, dgain_r );
    audio_ic_set_input_volume( 1, dgain_l );
#endif
        
    audio_ic_set_mgain( mgain );
    
#ifdef CONFIG_500D
    // nothing here yet.
#else

#ifndef CONFIG_550D // no sound with external mic?!
    audio_ic_write( AUDIO_IC_FIL1 | (enable_filters ? 0x1 : 0));
#endif
        
    // Enable loop mode and output digital volume2
    uint32_t mode3 = audio_ic_read( AUDIO_IC_MODE3 );
    mode3 &= ~0x5C; // disable loop, olvc, datt0/1
    audio_ic_write( AUDIO_IC_MODE3
                    | mode3                              // old value
                    | loopback0 << 6              // loop mode
                    | (o2gain & 0x3) << 2        // output volume
                    );
#endif /* CONFIG_500D nothing here yet*/
    
    //draw_audio_regs();
    /*bmp_printf( FONT_SMALL, 500, 450,
      "Gain %d/%d Mgain %d Src %d",
      dgain_l,
      dgain_r,
      mgain_index2gain(mgain),
      input_source
      );*/
    
    DebugMsg( DM_AUDIO, 3,
              "Gain mgain=%d dgain=%d/%d",
              mgain_index2gain(mgain),
              dgain_l,
              dgain_r
              );
}
#ifdef CONFIG_500D
static inline unsigned mgain_index2gain(int index) // sorted mgain values
{
    static uint8_t gains[] = { 0, 3, 6, 10, 17, 20, 23, 26, 29, 32 };
    index = COERCE(index, 0, 10);
    return gains[index];
}
static inline unsigned mgain_index2bits(int index) // sorted mgain values
{
    static uint8_t bitsv[] = { 0, 0x8, 0x9, 0x4, 0x5, 0x1, 0x6, 0x2, 0x7, 0x3 };
    index = COERCE(index, 0, 10);
    return bitsv[index];
}
#else
static inline unsigned mgain_index2gain(int index) // sorted mgain values
{
    static uint8_t gains[] = { 0, 10, 17, 20, 23, 26, 29, 32 };
    return gains[index & 0x7];
}
static inline unsigned mgain_index2bits(int index) // sorted mgain values
{
    static uint8_t bitsv[] = { 0, 0x4, 0x5, 0x01, 0x06, 0x02, 0x07, 0x03 };
    return bitsv[index & 0x7];
}
#endif


static inline uint8_t
audio_gain_to_cmd(
                  int                   gain
                  )
{
    unsigned cmd = ( gain * 1000 ) / 375 + 145;
    cmd &= 0xFF;
    
    return cmd;
}


static void check_sound_recording_warning(int x, int y)
{
    if (!SOUND_RECORDING_ENABLED) 
        {
            if (was_sound_recording_disabled_by_fps_override())
                {
                    if (!fps_should_record_wav())
                        menu_draw_icon(x, y, MNI_WARNING, (intptr_t) "Sound recording was disabled by FPS override.");
                }
            else
                menu_draw_icon(x, y, MNI_WARNING, (intptr_t) "Sound recording is disabled. Enable it from Canon menu.");
        }
}

static void
audio_3bit_toggle( void * priv, int delta )
{
    unsigned * ptr = priv;
    *ptr = (*ptr + 0x1) & 0x3;
    audio_configure( 1 );
}

static void
audio_3bit_toggle_reverse( void * priv, int delta )
{
    unsigned * ptr = priv;
    *ptr = (*ptr - 0x1) & 0x3;
    audio_configure( 1 );
}

static void
audio_mgain_toggle( void * priv, int delta )
{
    unsigned * ptr = priv;
#ifdef CONFIG_500D
    *ptr = mod((*ptr + 0x1), 10);
#else
    *ptr = (*ptr + 0x1) & 0x7;
#endif
    audio_configure( 1 );
}

static void
audio_mgain_toggle_reverse( void * priv, int delta )
{
    unsigned * ptr = priv;
#ifdef CONFIG_500D
    *ptr = mod((*ptr - 0x1), 10);
#else
    *ptr = (*ptr - 0x1) & 0x7;
#endif
    audio_configure( 1 );
}

static void
audio_binary_toggle( void * priv, int delta )
{
    unsigned * ptr = priv;
    *ptr = !*ptr;
    audio_configure( 1 );
}


static void
audio_mgain_display( void * priv, int x, int y, int selected )
{
    unsigned gain_index = *(unsigned*) priv;
#ifdef CONFIG_500D
    gain_index = COERCE(gain_index, 0, 10);
#else
    gain_index &= 0x7;
#endif
    
    bmp_printf(
               selected ? MENU_FONT_SEL : MENU_FONT,
               x, y,
               "Analog Gain   : %d dB",
               mgain_index2gain(gain_index)
               );
    check_sound_recording_warning(x, y);
    menu_draw_icon(x, y, MNI_PERCENT, mgain_index2gain(gain_index) * 100 / 32);
}

static void
audio_dgain_toggle( void * priv, int delta )
{
    unsigned dgain = *(unsigned*) priv;
    dgain += 6;
    if( dgain > 40 )
        dgain = 0;
    *(unsigned*) priv = dgain;
    audio_configure( 1 );
}

static void
audio_dgain_toggle_reverse( void * priv, int delta )
{
    unsigned dgain = *(unsigned*) priv;
    if( dgain <= 0 ) {
        dgain = 36;
    } else {
        dgain -= 6;
    }
    *(unsigned*) priv = dgain;
    audio_configure( 1 );
}

static void
audio_dgain_display( void * priv, int x, int y, int selected )
{
    unsigned val = *(unsigned*) priv;
    unsigned fnt = selected ? MENU_FONT_SEL : MENU_FONT;
    bmp_printf(
               FONT(fnt, val ? COLOR_RED : FONT_FG(fnt), FONT_BG(fnt)),
               x, y,
               // 23456789012
               "%s Digital Gain : %d dB",
               priv == &dgain_l ? "Left " : "Right",
               val
               );
    check_sound_recording_warning(x, y);
    if (!alc_enable){
        menu_draw_icon(x, y, MNI_PERCENT, val * 100 / 36);
    }else{
        menu_draw_icon(x, y, MNI_WARNING, (intptr_t) "AGC is enabled");
    }
}

static void
audio_lovl_display( void * priv, int x, int y, int selected )
{
    bmp_printf(
               selected ? MENU_FONT_SEL : MENU_FONT,
               x, y,
               //23456789012
               "Output volume : %d dB",
               2 * *(unsigned*) priv
               );
    check_sound_recording_warning(x, y);
    if (audio_monitoring) menu_draw_icon(x, y, MNI_PERCENT, (2 * *(unsigned*) priv) * 100 / 6);
    else menu_draw_icon(x, y, MNI_WARNING, (intptr_t) "Headphone monitoring is disabled");
}

static void
audio_input_toggle( void * priv, int delta )
{
    menu_quinternary_toggle(priv, 1);
    audio_configure( 1 );
}
static void
audio_input_toggle_reverse( void * priv, int delta )
{
    menu_quinternary_toggle_reverse(priv, -1);
    audio_configure( 1 );
}

void audio_filters_display( void * priv, int x, int y, int selected )
{
    bmp_printf(
               selected ? MENU_FONT_SEL : MENU_FONT,
               x, y,
               "Wind Filter   : %s",
               enable_filters ? "ON" : "OFF"
               );
    check_sound_recording_warning(x, y);
}

/*
  static void
  audio_loopback_display( void * priv, int x, int y, int selected )
  {
  bmp_printf(
  selected ? MENU_FONT_SEL : MENU_FONT,
  x, y,
  "Loopback      : %s",
  loopback ? "ON " : "OFF"
  );
  }*/

/*
  PROP_INT(PROP_WINDCUT_MODE, windcut_mode);
 
  void windcut_display( void * priv, int x, int y, int selected )
  {
  bmp_printf(
  selected ? MENU_FONT_SEL : MENU_FONT,
  x, y,
  "Wind Cut Mode : %d",
  windcut_mode
  );
  }
 
  void set_windcut(int value)
  {
  prop_request_change(PROP_WINDCUT_MODE, &value, 4);
  }
 
  void windcut_toggle(void* priv)
  {
  windcut_mode = !windcut_mode;
  set_windcut(windcut_mode);
  }*/

static void
audio_micpower_display( void * priv, int x, int y, int selected )
{
    unsigned int mic_pow = get_mic_power(get_input_source());
    bmp_printf(
               selected ? MENU_FONT_SEL : MENU_FONT,
               x, y,
               "Mic Power     : %s",
               mic_pow ? "ON (Low Z)" : "OFF (High Z)"
               );
    check_sound_recording_warning(x, y);
    if (mic_pow != mic_power) menu_draw_icon(x,y, MNI_WARNING, (intptr_t) "Mic power is required by internal mic.");
}

static struct menu_entry audio_menus[] = {
#if !(defined(CONFIG_1100D) || defined(CONFIG_5D3) || defined(CONFIG_7D))
#if 0
    {
        .priv           = &o2gain,
        .select         = audio_o2gain_toggle,
        .display        = audio_o2gain_display,
    },
#endif
    {
        .name = "Analog Gain",
        .priv           = &mgain,
        .select         = audio_mgain_toggle,
        .select_reverse = audio_mgain_toggle_reverse,
        .display        = audio_mgain_display,
        .help = "Gain applied to both inputs in analog domain (preferred).",
        //.essential = FOR_MOVIE,
        .edit_mode = EM_MANY_VALUES,
    },
#ifndef CONFIG_500D
    {
        .name = "Digital Gain...", 
        .select = menu_open_submenu, 
        .help = "Digital gain (not recommended, use only for headphones!)",
        .children =  (struct menu_entry[]) {
            {
                .name = "Left Digital Gain ",
                .priv           = &dgain_l,
                .select         = audio_dgain_toggle,
                .select_reverse = audio_dgain_toggle_reverse,
                .display        = audio_dgain_display,
                .help = "Digital gain (LEFT). Any nonzero value reduces quality.",
                .edit_mode = EM_MANY_VALUES,
            },
            {
                .name = "Right Digital Gain",
                .priv           = &dgain_r,
                .select         = audio_dgain_toggle,
                .select_reverse = audio_dgain_toggle_reverse,
                .display        = audio_dgain_display,
                .help = "Digital gain (RIGHT). Any nonzero value reduces quality.",
                .edit_mode = EM_MANY_VALUES,
            },
            {
                .name = "AGC",
                .priv           = &alc_enable,
                .select         = audio_binary_toggle,
                .display        = audio_alc_display,
                .help = "Automatic Gain Control - turn it off :)",
                //~ .icon_type = IT_DISABLE_SOME_FEATURE_NEG,
                //.essential = FOR_MOVIE, // nobody needs to toggle this, but newbies want to see "AGC:OFF", manual controls are not enough...
            },
            MENU_EOL,
        },
    },
    {
        .name = "Input source",
        .priv           = &input_choice,
        .select         = audio_input_toggle,
        .select_reverse         = audio_input_toggle_reverse,
        .display        = audio_input_display,
        .help = "Audio input: internal / external / both / balanced / auto.",
        //.essential = FOR_MOVIE,
        //~ .edit_mode = EM_MANY_VALUES,
    },
#endif
    /*{
      .priv              = &windcut_mode,
      .select            = windcut_toggle,
      .display   = windcut_display,
      },*/
#if !defined(CONFIG_550D) && !defined(CONFIG_500D)
    {
        .name = "Wind Filter",
        .priv              = &enable_filters,
        .display           = audio_filters_display,
        .help = "High pass filter for wind noise reduction.",
        .select            = audio_binary_toggle,
        //~ .icon_type = IT_DISABLE_SOME_FEATURE,
        //.essential = FOR_MOVIE,
    },
#endif
#ifdef CONFIG_AUDIO_REG_LOG
    {
        .priv           = "Close register log",
        .select         = audio_reg_close,
        .display        = menu_print,
    },
#endif
    /*{
      .priv              = &loopback,
      .select            = audio_binary_toggle,
      .display   = audio_loopback_display,
      },*/
#if !defined(CONFIG_500D)
    {
        .name = "Mic Power",
        .priv           = &mic_power,
        .select         = audio_binary_toggle,
        .display        = audio_micpower_display,
        .help = "Needed for int. and some other mics, but lowers impedance.",
        //.essential = FOR_MOVIE,
    },
    {
        .name = "Output volume",
        .priv           = &lovl,
        .select         = audio_3bit_toggle,
        .select_reverse = audio_3bit_toggle_reverse,
        .display        = audio_lovl_display,
        .help = "Output volume for audio monitoring (headphones only).",
        //~ .edit_mode = EM_MANY_VALUES,
    },

#endif /*ifNNNdef CONFIG_500D*/
    {
        .name = "Headphone Monitoring",
        .priv = &audio_monitoring,
        .select         = audio_monitoring_toggle,
        .display        = audio_monitoring_display,
        .help = "Monitoring via A-V jack. Disable if you use a SD display.",
        //.essential = FOR_MOVIE,
    },
#endif /* ifNNNdef CONFIG_1100D */
    {
        .name = "Audio Meters",
        .priv           = &cfg_draw_meters,
        .select         = menu_binary_toggle,
        .display        = audio_meter_display,
        .help = "Bar peak decay, -40...0 dB, yellow at -12 dB, red at -3 dB.",
        //.essential = FOR_MOVIE,
    },
};


void sounddev_task();


/** Replace the sound dev task with our own to disable AGC.
 *
 * This task disables the AGC when the sound device is activated.
 */
static void
my_sounddev_task()
{
    msleep( 1500 );
    if (magic_is_off()) { sounddev_task(); return; }
    
    hold_your_horses(1);
    
    DebugMsg( DM_AUDIO, 3,
              "!!!!! %s started sem=%x",
              __func__,
              (uint32_t) sounddev.sem_alc
              );
    
    //DIY debug ..
    //~ bmp_printf( FONT_SMALL, 500, 400,
    //~ "sddvtsk, param=%d",
    //~ some_param
    //~ );      
    
    gain.sem = create_named_semaphore( "audio_gain", 1 );
    
    // Fake the sound dev task parameters
    sounddev.sem_alc = create_named_semaphore( 0, 0 );
    
    sounddev_active_in(0,0);
    
    audio_configure( 1 ); // force it this time
    
#ifdef CONFIG_AUDIO_REG_LOG
    // Create the logging file
    reg_file = FIO_CreateFileEx(CARD_DRIVE "ML/audioreg.txt" );
#endif
    
    msleep(500);
    audio_monitoring_update();
    
    while(1)
        {
            // will be unlocked by the property handler
            int rc = take_semaphore( gain.sem, recording && MVR_FRAME_NUMBER < 30 ? 100 : 1000 );
            if(gui_state != GUISTATE_PLAYMENU || (audio_monitoring && AUDIO_MONITORING_HEADPHONES_CONNECTED)) {
                audio_configure( rc == 0 ); // force it if we got the semaphore
            }
        }
}

#if !defined(CONFIG_5D3) && !defined(CONFIG_7D)
TASK_OVERRIDE( sounddev_task, my_sounddev_task );
#endif

#if 0
/** Replace the audio level task with our own.
 *
 * This task runs when the sound device is activated to keep track of
 * the average audio level and translate it to dB.  Nothing ever seems
 * to activate it, so it is commented out for now.
 */
static void
my_audio_level_task( void )
{
    //const uint32_t * const thresholds = (void*) 0xFFC60ABC;
    DebugMsg( DM_AUDIO, 3, "!!!!! %s: Replaced Canon task %x", __func__, audio_level_task );
    
    audio_in.gain           = -40;
    audio_in.sample_count   = 0;
    audio_in.max_sample     = 0;
    audio_in.sem_interval   = create_named_semaphore( 0, 1 );
    audio_in.sem_task       = create_named_semaphore( 0, 0 );
    
    while(1)
        {
            DebugMsg( DM_AUDIO, 3, "%s: sleeping init=%d",
                      __func__,
                      audio_in.initialized
                      );
        
            if( take_semaphore( audio_in.sem_interval, 0 ) & 1 )
                {
                    //DebugAssert( "!IS_ERROR", "SoundDevice sem_interval", 0x82 );
                    break;
                }
        
            if( take_semaphore( audio_in.sem_task, 0 ) & 1 )
                {
                    //DebugAssert( "!IS_ERROR", SoundDevice", 0x83 );
                    break;
                }
        
            DebugMsg( DM_AUDIO, 3, "%s: awake init=%d\n", __func__, audio_in.initialized );
        
            if( !audio_in.initialized )
                {
                    DebugMsg( DM_AUDIO, 3, "**** %s: agc=%d/%d wind=%d volume=%d",
                              __func__,
                              audio_in.agc_on,
                              audio_in.last_agc_on,
                              audio_in.windcut,
                              audio_in.volume
                              );
            
                    audio_set_filter_off();
            
                    if( audio_in.last_agc_on == 1
                        &&  audio_in.agc_on == 0
                        )
                        audio_set_alc_off();
                        
                    audio_in.last_agc_on = audio_in.agc_on;
                    audio_set_windcut( audio_in.windcut );
            
                    audio_set_sampling_param( 44100, 0x10, 1 );
                    audio_set_volume_in(
                                        audio_in.agc_on,
                                        audio_in.volume
                                        );
            
                    if( audio_in.agc_on == 1 )
                        audio_set_alc_on();
            
                    audio_in.initialized    = 1;
                    audio_in.gain           = -39;
                    audio_in.sample_count   = 0;
            
                }
        
            if( audio_in.asif_started == 0 )
                {
                    DebugMsg( DM_AUDIO, 3, "%s: Starting asif observer", __func__ );
                    audio_start_asif_observer();
                    audio_in.asif_started = 1;
                }
        
            //uint32_t level = audio_read_level(0);
            give_semaphore( audio_in.sem_task );
        
            // Never adjust it!
            //set_audio_agc();
            //if( file != (void*) 0xFFFFFFFF )
            //FIO_WriteFile( file, &level, sizeof(level) );
        
            // audio_interval_wakeup will unlock our semaphore
            oneshot_timer( 0x200, audio_interval_unlock, audio_interval_unlock, 0 );
        }
    
    DebugMsg( DM_AUDIO, 3, "!!!!! %s task exited????", __func__ );
}

TASK_OVERRIDE( audio_level_task, my_audio_level_task );
#endif

static void volume_display()
{
    int mgain_db = mgain_index2gain(mgain);
    NotifyBox(2000, "Volume: %d + (%d,%d) dB", mgain_db, dgain_l, dgain_r);
}

void volume_up()
{
    int mgain_db = mgain_index2gain(mgain);
    if (mgain_db < 32)
        audio_mgain_toggle(&mgain, 0);
    else
        {
            if( MAX(dgain_l, dgain_r) + 6 <= 40 )
                {
                    audio_dgain_toggle(&dgain_l, 0);
                    audio_dgain_toggle(&dgain_r, 0);
                }
        }
    volume_display();
}

void volume_down()
{
    int mgain_db = mgain_index2gain(mgain);
    
    if( MIN(dgain_l, dgain_r) > 0 )
        {
            audio_dgain_toggle_reverse(&dgain_l, 0);
            audio_dgain_toggle_reverse(&dgain_r, 0);
        }
    else if (mgain_db > 0)
        audio_mgain_toggle_reverse(&mgain, 0);
    volume_display();
}

static void out_volume_display()
{
    //int mgain_db = mgain_index2gain(mgain);
    NotifyBox(2000, "Out Volume: %d dB", 2 * lovl);
}
void out_volume_up()
{
    int* p = (int*) &lovl;
    *p = COERCE(*p + 1, 0, 3);
    out_volume_display();
}
void out_volume_down()
{
    int* p = (int*) &lovl;
    *p = COERCE(*p - 1, 0, 3);
    out_volume_display();
}


static void audio_menus_init()
{
#if defined(CONFIG_5D3_MINIMAL) || defined(CONFIG_7D_MINIMAL)
    menu_add( "Overlay", audio_menus, COUNT(audio_menus) );
#else
    menu_add( "Audio", audio_menus, COUNT(audio_menus) );
#endif
}


INIT_FUNC("audio.init", audio_menus_init);
back to top