1
0
Fork 0
forked from len0rd/rockbox

Added FS#2939 Encoder Codec Interface + Codecs by Antonius Hellmann with additional FM Recording support and my modifications

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10789 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2006-08-28 22:38:41 +00:00
parent 65c2c58b3a
commit 4fc717a4c1
36 changed files with 4803 additions and 860 deletions

View file

@ -40,6 +40,7 @@
#include "mpeg.h"
#include "buffer.h"
#include "mp3_playback.h"
#include "playback.h"
#include "backlight.h"
#include "ata.h"
#include "talk.h"
@ -208,11 +209,28 @@ struct codec_api ci = {
profile_func_exit,
#endif
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
false,
enc_get_inputs,
enc_set_parameters,
enc_alloc_chunk,
enc_free_chunk,
enc_wavbuf_near_empty,
enc_get_wav_data,
&enc_set_header_callback,
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
};
void codec_get_full_path(char *path, const char *codec_fn)
{
/* Create full codec path */
snprintf(path, MAX_PATH-1, ROCKBOX_DIR CODECS_DIR "/%s", codec_fn);
}
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
struct codec_api *api)
{
@ -277,15 +295,18 @@ int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
int codec_load_file(const char *plugin, struct codec_api *api)
{
char msgbuf[80];
char path[MAX_PATH];
int fd;
int rc;
codec_get_full_path(path, plugin);
/* zero out codec buffer to ensure a properly zeroed bss area */
memset(codecbuf, 0, CODEC_SIZE);
fd = open(plugin, O_RDONLY);
fd = open(path, O_RDONLY);
if (fd < 0) {
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", plugin);
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", path);
logf("Codec load error:%d", fd);
gui_syncsplash(HZ*2, true, msgbuf);
return fd;

View file

@ -46,6 +46,9 @@
#include "profile.h"
#endif
#if (CONFIG_CODEC == SWCODEC)
#if !defined(SIMULATOR)
#include "pcm_record.h"
#endif
#include "dsp.h"
#include "playback.h"
#endif
@ -84,7 +87,7 @@
#define CODEC_MAGIC 0x52434F44 /* RCOD */
/* increase this every time the api struct changes */
#define CODEC_API_VERSION 8
#define CODEC_API_VERSION 9
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@ -284,6 +287,21 @@ struct codec_api {
void (*profile_func_enter)(void *this_fn, void *call_site);
void (*profile_func_exit)(void *this_fn, void *call_site);
#endif
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
bool enc_codec_loaded;
void (*enc_get_inputs)(int *buffer_size,
int *channels, int *quality);
void (*enc_set_parameters)(int chunk_size, int num_chunks,
int samp_per_chunk, char *head_ptr, int head_size,
int enc_id);
unsigned int* (*enc_alloc_chunk)(void);
void (*enc_free_chunk)(void);
int (*enc_wavbuf_near_empty)(void);
char* (*enc_get_wav_data)(int size);
void (**enc_set_header_callback)(void *head_buffer,
int head_size, int num_samples, bool is_file_header);
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
@ -317,6 +335,10 @@ extern unsigned char plugin_end_addr[];
#endif
#endif
/* create full codec path from filenames in audio_formats[]
assumes buffer size is MAX_PATH */
void codec_get_full_path(char *path, const char *codec_fn);
/* defined by the codec loader (codec.c) */
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
struct codec_api *api);

View file

@ -58,6 +58,9 @@ $(OBJDIR)/wavpack.elf : $(OBJDIR)/wavpack.o $(BUILDDIR)/libwavpack.a
$(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a
$(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a
$(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a
$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o
$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o
$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a
$(OBJDIR)/%.elf :
@echo "LD $(notdir $@)"

View file

@ -1,4 +1,5 @@
#if CONFIG_CODEC == SWCODEC
/* decoders */
vorbis.c
mpa.c
flac.c
@ -13,4 +14,11 @@ aac.c
shorten.c
aiff.c
sid.c
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* encoders */
mp3_enc.c
wav_enc.c
wavpack_enc.c
#endif
#endif

2860
apps/codecs/mp3_enc.c Normal file

File diff suppressed because it is too large Load diff

172
apps/codecs/wav_enc.c Normal file
View file

@ -0,0 +1,172 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Antonius Hellmann
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef SIMULATOR
#include "codeclib.h"
CODEC_HEADER
static struct codec_api *ci;
static int enc_channels;
#define CHUNK_SIZE 8192
static unsigned char wav_header[44] =
{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
static unsigned char wav_header_mono[44] =
{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
/* update file header info callback function (called by main application) */
void enc_set_header(void *head_buffer, /* ptr to the file header data */
int head_size, /* size of this header data */
int num_pcm_samples, /* amount of processed pcm samples */
bool is_file_header)
{
int num_file_bytes = num_pcm_samples * 2 * enc_channels;
if(is_file_header)
{
/* update file header before file closing */
if((int)sizeof(wav_header) < head_size)
{
/* update wave header size entries: special to WAV format */
*(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36);
*(long*)(head_buffer+40) = htole32(num_file_bytes);
}
}
}
/* main codec entry point */
enum codec_status codec_start(struct codec_api* api)
{
int i;
long lr;
unsigned long t;
unsigned long *src;
unsigned long *dst;
int chunk_size, num_chunks, samp_per_chunk;
int enc_buffer_size;
int enc_quality;
bool cpu_boosted = true; /* start boosted */
ci = api; // copy to global api pointer
if(ci->enc_get_inputs == NULL ||
ci->enc_set_parameters == NULL ||
ci->enc_alloc_chunk == NULL ||
ci->enc_free_chunk == NULL ||
ci->enc_wavbuf_near_empty == NULL ||
ci->enc_get_wav_data == NULL ||
ci->enc_set_header_callback == NULL )
return CODEC_ERROR;
ci->cpu_boost(true);
*ci->enc_set_header_callback = enc_set_header;
ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
/* configure the buffer system */
chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
num_chunks = enc_buffer_size / chunk_size;
samp_per_chunk = CHUNK_SIZE / 4;
/* inform the main program about buffer dimensions and other params */
ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
(enc_channels == 2) ? wav_header : wav_header_mono,
sizeof(wav_header), AFMT_PCM_WAV);
/* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = true;
/* main encoding loop */
while(!ci->stop_codec)
{
while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
{
if(ci->stop_codec)
break;
if(ci->enc_wavbuf_near_empty() == 0)
{
if(!cpu_boosted)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
}
dst = (unsigned long*)ci->enc_alloc_chunk();
*dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */
if(enc_channels == 2)
{
/* swap byte order & copy to destination */
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = *src++;
*dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
}
}
else
{
/* mix left/right, swap byte order & copy to destination */
for (i=0; i<CHUNK_SIZE/8; i++)
{
lr = (long)*src++;
lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
t = (lr << 16);
lr = (long)*src++;
lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
t |= lr & 0xffff;
*dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
}
}
ci->enc_free_chunk();
ci->yield();
}
if(ci->enc_wavbuf_near_empty())
{
if(cpu_boosted)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
}
ci->yield();
}
if(cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
/* reset parameters to initial state */
ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
/* main application waits for this flag during encoder removing */
ci->enc_codec_loaded = false;
return CODEC_OK;
}
#endif

230
apps/codecs/wavpack_enc.c Normal file
View file

@ -0,0 +1,230 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Antonius Hellmann
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef SIMULATOR
#include "codeclib.h"
#include "libwavpack/wavpack.h"
CODEC_HEADER
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
static unsigned char wav_header_ster [46] =
{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
static unsigned char wav_header_mono [46] =
{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
static struct codec_api *ci;
static int enc_channels;
#define CHUNK_SIZE 20000
static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
void *memset(void *s, int c, size_t n)
{
return(ci->memset(s,c,n));
}
void *memcpy(void *dest, const void *src, size_t n)
{
return(ci->memcpy(dest,src,n));
}
/* update file header info callback function */
void enc_set_header(void *head_buffer, /* ptr to the file header data */
int head_size, /* size of this header data */
int num_pcm_sampl, /* amount of processed pcm samples */
bool is_file_header) /* update file/chunk header */
{
if(is_file_header)
{
/* update file header before file closing */
if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
{
char* riff_header = (char*)head_buffer + sizeof(WavpackHeader);
char* wv_header = (char*)head_buffer + sizeof(wav_header_mono);
int num_file_bytes = num_pcm_sampl * 2 * enc_channels;
unsigned long ckSize;
/* RIFF header and WVPK header have to be swapped */
/* copy wavpack header to file start position */
ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
wv_header = head_buffer; /* recalc wavpack header position */
if(enc_channels == 2)
ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
else
ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
/* update the Wavpack header first chunk size & total frame count */
ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
+ sizeof(wav_header_mono);
((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
/* update the RIFF WAV header size entries */
*(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
*(long*)(riff_header+42) = htole32(num_file_bytes);
}
}
else
{
/* update timestamp (block_index) */
((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
}
}
enum codec_status codec_start(struct codec_api* api)
{
int i;
long t;
uint32 *src;
uint32 *dst;
int chunk_size, num_chunks, samp_per_chunk;
int enc_buffer_size;
int enc_quality;
WavpackConfig config;
WavpackContext *wpc;
bool cpu_boosted = true; /* start boosted */
ci = api; // copy to global api pointer
if(ci->enc_get_inputs == NULL ||
ci->enc_set_parameters == NULL ||
ci->enc_alloc_chunk == NULL ||
ci->enc_free_chunk == NULL ||
ci->enc_wavbuf_near_empty == NULL ||
ci->enc_get_wav_data == NULL ||
ci->enc_set_header_callback == NULL )
return CODEC_ERROR;
ci->cpu_boost(true);
*ci->enc_set_header_callback = enc_set_header;
ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
/* configure the buffer system */
chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
num_chunks = enc_buffer_size / chunk_size;
samp_per_chunk = CHUNK_SIZE / 4;
/* inform the main program about buffer dimensions and other params */
/* add wav_header_mono as place holder to file start position */
/* wav header and wvpk header have to be reordered later */
ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
wav_header_mono, sizeof(wav_header_mono),
AFMT_WAVPACK);
wpc = WavpackOpenFileOutput ();
memset (&config, 0, sizeof (config));
config.bits_per_sample = 16;
config.bytes_per_sample = 2;
config.sample_rate = 44100;
config.num_channels = enc_channels;
if (!WavpackSetConfiguration (wpc, &config, 1))
return CODEC_ERROR;
/* main application waits for this flag during encoder loading */
ci->enc_codec_loaded = true;
/* main encoding loop */
while(!ci->stop_codec)
{
while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
{
if(ci->stop_codec)
break;
if(ci->enc_wavbuf_near_empty() == 0)
{
if(!cpu_boosted)
{
ci->cpu_boost(true);
cpu_boosted = true;
}
}
dst = (uint32*)ci->enc_alloc_chunk() + 1;
WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
if(enc_channels == 2)
{
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = (long)*src++;
input_buffer[2*i + 0] = t >> 16;
input_buffer[2*i + 1] = (short)t;
}
}
else
{
for (i=0; i<CHUNK_SIZE/4; i++)
{
t = (long)*src++;
t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
input_buffer[i] = t;
}
}
if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
return CODEC_ERROR;
/* finish the chunk and store chunk size info */
dst[-1] = WavpackFinishBlock (wpc);
ci->enc_free_chunk();
ci->yield();
}
if(ci->enc_wavbuf_near_empty())
{
if(cpu_boosted)
{
ci->cpu_boost(false);
cpu_boosted = false;
}
}
ci->yield();
}
if(cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
/* reset parameters to initial state */
ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
/* main application waits for this flag during encoder removing */
ci->enc_codec_loaded = false;
return CODEC_OK;
}
#endif

View file

@ -445,9 +445,8 @@ int ft_enter(struct tree_context* c)
{
set_file(buf, global_settings.fmr_file, MAX_FILENAME);
radio_load_presets(global_settings.fmr_file);
if(get_radio_status() != FMRADIO_PLAYING &&
get_radio_status() != FMRADIO_PAUSED)
radio_screen();
if(!in_radio_screen())
radio_screen();
}
/*
* Preset outside default folder, we can choose such only

View file

@ -9661,6 +9661,22 @@
*: "Full Path"
</voice>
</phrase>
<<<<<<< english.lang
<phrase>
id: VOICE_KBIT_PER_SEC
desc: spoken only, for file extension
user:
<source>
*: ""
</source>
<dest>
*: ""
</dest>
<voice>
*: "kilobits per second"
</voice>
</phrase>
=======
<phrase>
id: LANG_RECORD_AGC_PRESET
desc: automatic gain control in record settings
@ -9778,3 +9794,4 @@
*: "AGC maximum gain"
</voice>
</phrase>
>>>>>>> 1.267

View file

@ -285,9 +285,31 @@ static bool custom_theme_browse(void)
#ifdef HAVE_RECORDING
static bool rec_menu_recording_screen(void)
{
return recording_screen(false);
}
static bool recording_settings(void)
{
return recording_menu(false);
bool ret;
#ifdef HAVE_FMRADIO_IN
int rec_source = global_settings.rec_source;
#endif
ret = recording_menu(false);
#ifdef HAVE_FMRADIO_IN
if (rec_source != global_settings.rec_source)
{
if (rec_source == AUDIO_SRC_FMRADIO)
radio_stop();
/* If AUDIO_SRC_FMRADIO was selected from something else,
the recording screen will start the radio */
}
#endif
return ret;
}
bool rec_menu(void)
@ -297,7 +319,7 @@ bool rec_menu(void)
/* recording menu */
static const struct menu_item items[] = {
{ ID2P(LANG_RECORDING_MENU), recording_screen },
{ ID2P(LANG_RECORDING_MENU), rec_menu_recording_screen },
{ ID2P(LANG_RECORDING_SETTINGS), recording_settings},
};

View file

@ -74,29 +74,18 @@
#include "misc.h"
#include "sound.h"
#include "metadata.h"
#include "talk.h"
#ifdef CONFIG_TUNER
#include "radio.h"
#endif
#include "splash.h"
#include "talk.h"
#ifdef HAVE_RECORDING
#include "recording.h"
#endif
static volatile bool audio_codec_loaded;
static volatile bool voice_codec_loaded;
static volatile bool playing;
static volatile bool paused;
#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
#define CODEC_FLAC "/.rockbox/codecs/flac.codec"
#define CODEC_WAV "/.rockbox/codecs/wav.codec"
#define CODEC_A52 "/.rockbox/codecs/a52.codec"
#define CODEC_MPC "/.rockbox/codecs/mpc.codec"
#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"
#define CODEC_ALAC "/.rockbox/codecs/alac.codec"
#define CODEC_AAC "/.rockbox/codecs/aac.codec"
#define CODEC_SHN "/.rockbox/codecs/shorten.codec"
#define CODEC_AIFF "/.rockbox/codecs/aiff.codec"
#define CODEC_SID "/.rockbox/codecs/sid.codec"
/* default point to start buffer refill */
#define AUDIO_DEFAULT_WATERMARK (1024*512)
@ -133,6 +122,11 @@ enum {
Q_CODEC_LOAD,
Q_CODEC_LOAD_DISK,
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
Q_ENCODER_LOAD_DISK,
Q_ENCODER_RECORD,
#endif
};
/* As defined in plugins/lib/xxx2wav.h */
@ -382,7 +376,7 @@ static bool voice_pcmbuf_insert_split_callback(
}
return true;
}
} /* voice_pcmbuf_insert_split_callback */
static bool codec_pcmbuf_insert_split_callback(
const void *ch1, const void *ch2, size_t length)
@ -444,7 +438,7 @@ static bool codec_pcmbuf_insert_split_callback(
}
return true;
}
} /* codec_pcmbuf_insert_split_callback */
static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
{
@ -649,7 +643,7 @@ static size_t codec_filebuf_callback(void *ptr, size_t size)
/* Return the actual amount of data copied to the buffer */
return copy_n;
}
} /* codec_filebuf_callback */
static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
{
@ -664,7 +658,9 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
while (1)
{
if (voice_is_playing)
{
queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
}
else if (playing)
{
queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
@ -679,7 +675,11 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
if (playing)
swap_codec();
break;
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
case Q_ENCODER_RECORD:
swap_codec();
break;
#endif
case Q_VOICE_STOP:
if (voice_is_playing)
{
@ -743,7 +743,7 @@ voice_play_clip:
return NULL;
return voicebuf;
}
} /* voice_request_buffer_callback */
static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
{
@ -794,7 +794,7 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
*realsize = copy_n;
return (char *)&filebuf[buf_ridx];
}
} /* codec_request_buffer_callback */
static int get_codec_base_type(int type)
{
@ -1531,52 +1531,24 @@ static void codec_discard_codec_callback(void)
#endif
}
static const char *get_codec_path(int codectype)
static const char * get_codec_filename(int enc_spec)
{
switch (codectype) {
case AFMT_OGG_VORBIS:
logf("Codec: Vorbis");
return CODEC_VORBIS;
case AFMT_MPA_L1:
case AFMT_MPA_L2:
case AFMT_MPA_L3:
logf("Codec: MPA L1/L2/L3");
return CODEC_MPA_L3;
case AFMT_PCM_WAV:
logf("Codec: PCM WAV");
return CODEC_WAV;
case AFMT_FLAC:
logf("Codec: FLAC");
return CODEC_FLAC;
case AFMT_A52:
logf("Codec: A52");
return CODEC_A52;
case AFMT_MPC:
logf("Codec: Musepack");
return CODEC_MPC;
case AFMT_WAVPACK:
logf("Codec: WAVPACK");
return CODEC_WAVPACK;
case AFMT_ALAC:
logf("Codec: ALAC");
return CODEC_ALAC;
case AFMT_AAC:
logf("Codec: AAC");
return CODEC_AAC;
case AFMT_SHN:
logf("Codec: SHN");
return CODEC_SHN;
case AFMT_AIFF:
logf("Codec: PCM AIFF");
return CODEC_AIFF;
case AFMT_SID:
logf("Codec: SID");
return CODEC_SID;
default:
logf("Codec: Unsupported");
return NULL;
}
}
const char *fname;
int type = enc_spec & CODEC_TYPE_MASK;
int afmt = enc_spec & CODEC_AFMT_MASK;
if ((unsigned)afmt >= AFMT_NUM_CODECS)
type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
fname = (type == CODEC_TYPE_DECODER) ?
audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
logf("%s: %d - %s",
(type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
afmt, fname ? fname : "<unknown>");
return fname;
} /* get_codec_filename */
static bool loadcodec(bool start_play)
{
@ -1585,9 +1557,10 @@ static bool loadcodec(bool start_play)
int rc;
size_t copy_n;
int prev_track;
char codec_path[MAX_PATH]; /* Full path to codec */
const char *codec_path = get_codec_path(tracks[track_widx].id3.codectype);
if (codec_path == NULL)
const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
if (codec_fn == NULL)
return false;
tracks[track_widx].has_codec = false;
@ -1603,7 +1576,7 @@ static bool loadcodec(bool start_play)
ci.taginfo_ready = &cur_ti->taginfo_ready;
ci.curpos = 0;
playing = true;
queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path);
queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
return true;
}
else
@ -1625,6 +1598,8 @@ static bool loadcodec(bool start_play)
}
}
codec_get_full_path(codec_path, codec_fn);
fd = open(codec_path, O_RDONLY);
if (fd < 0)
{
@ -1973,11 +1948,8 @@ static void audio_stop_playback(void)
(playlist_end && ci.stop_codec)?NULL:audio_current_track());
}
if (voice_is_playing)
{
while (voice_is_playing && !queue_empty(&voice_codec_queue))
yield();
}
while (voice_is_playing && !queue_empty(&voice_codec_queue))
yield();
filebufused = 0;
playing = false;
@ -1998,10 +1970,8 @@ static void audio_stop_playback(void)
static void audio_play_start(size_t offset)
{
#ifdef CONFIG_TUNER
/* check if radio is playing */
if (get_radio_status() != FMRADIO_OFF)
radio_stop();
#if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#endif
/* Wait for any previously playing audio to flush - TODO: Not necessary? */
@ -2483,6 +2453,20 @@ static void codec_thread(void)
mutex_unlock(&mutex_codecthread);
break ;
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
case Q_ENCODER_LOAD_DISK:
logf("Encoder load disk");
audio_codec_loaded = false;
if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
queue_post(&voice_codec_queue, Q_ENCODER_RECORD, NULL);
mutex_lock(&mutex_codecthread);
current_codec = CODEC_IDX_AUDIO;
ci.stop_codec = false;
status = codec_load_file((const char *)ev.data, &ci);
mutex_unlock(&mutex_codecthread);
break;
#endif
#ifndef SIMULATOR
case SYS_USB_CONNECTED:
queue_clear(&codec_queue);
@ -2511,8 +2495,6 @@ static void codec_thread(void)
case Q_CODEC_LOAD:
if (playing)
{
const char *codec_path;
if (ci.new_track || status != CODEC_OK)
{
if (!ci.new_track)
@ -2523,7 +2505,8 @@ static void codec_thread(void)
if (!load_next_track())
{
queue_post(&codec_queue, Q_AUDIO_STOP, 0);
// queue_post(&codec_queue, Q_AUDIO_STOP, 0);
queue_post(&audio_queue, Q_AUDIO_STOP, 0);
break;
}
}
@ -2545,12 +2528,12 @@ static void codec_thread(void)
queue_post(&codec_queue, Q_CODEC_LOAD, 0);
else
{
codec_path = get_codec_path(cur_ti->id3.codectype);
queue_post(&codec_queue,
Q_CODEC_LOAD_DISK, (void *)codec_path);
const char *codec_fn = get_codec_filename(cur_ti->id3.codectype);
queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
(void *)codec_fn);
}
}
}
} /* end switch */
}
}
@ -2596,6 +2579,37 @@ static void reset_buffer(void)
filebuflen &= ~3;
}
void audio_load_encoder(int enc_id)
{
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
if (!enc_fn)
return;
audio_remove_encoder();
queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
while (!ci.enc_codec_loaded)
yield();
#endif
return;
(void)enc_id;
} /* audio_load_encoder */
void audio_remove_encoder(void)
{
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* force encoder codec unload (if previously loaded) */
if (!ci.enc_codec_loaded)
return;
ci.stop_codec = true;
while (ci.enc_codec_loaded)
yield();
#endif
} /* audio_remove_encoder */
static void voice_codec_thread(void)
{
while (1)
@ -2608,13 +2622,13 @@ static void voice_codec_thread(void)
voice_remaining = 0;
voice_getmore = NULL;
codec_load_file(CODEC_MPA_L3, &ci_voice);
codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
logf("Voice codec finished");
mutex_unlock(&mutex_codecthread);
voice_codec_loaded = false;
mutex_unlock(&mutex_codecthread);
}
}
} /* voice_codec_thread */
void voice_init(void)
{
@ -2642,7 +2656,20 @@ void voice_init(void)
while (!voice_codec_loaded)
yield();
}
} /* voice_init */
void voice_stop(void)
{
/* Messages should not be posted to voice codec queue unless it is the
current codec or deadlocks happen. This will be addressed globally soon.
-- jhMikeS */
if (current_codec != CODEC_IDX_VOICE)
return;
mp3_play_stop();
while (voice_is_playing && !queue_empty(&voice_codec_queue))
yield();
} /* voice_stop */
struct mp3entry* audio_current_track(void)
{
@ -2803,9 +2830,19 @@ int audio_status(void)
if (paused)
ret |= AUDIO_STATUS_PAUSE;
#ifdef HAVE_RECORDING
/* Do this here for constitency with mpeg.c version */
ret |= pcm_rec_status();
#endif
return ret;
}
bool audio_query_poweroff(void)
{
return !(playing && paused);
}
int audio_get_file_pos(void)
{
return 0;

View file

@ -27,8 +27,8 @@
#include "id3.h"
#include "mp3data.h"
#define CODEC_IDX_AUDIO 0
#define CODEC_IDX_VOICE 1
#define CODEC_IDX_AUDIO 0
#define CODEC_IDX_VOICE 1
/* Not yet implemented. */
#define CODEC_SET_AUDIOBUF_WATERMARK 4
@ -66,6 +66,7 @@ void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
bool last_track));
void audio_invalidate_tracks(void);
void voice_init(void);
void voice_stop(void);
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
extern void audio_next_dir(void);

View file

@ -24,7 +24,6 @@
#include "mas.h"
#include "settings.h"
#include "button.h"
#include "fmradio.h"
#include "status.h"
#include "kernel.h"
#include "mpeg.h"
@ -63,17 +62,6 @@
#ifdef CONFIG_TUNER
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_UDA1380
#include "uda1380.h"
#endif
#ifdef HAVE_TLV320
#include "tlv320.h"
#endif
#include "pcm_record.h"
#endif
#if CONFIG_KEYPAD == RECORDER_PAD
#define FM_MENU BUTTON_F1
#define FM_PRESET BUTTON_F2
@ -165,6 +153,7 @@ static int curr_freq;
static int radio_mode = RADIO_SCAN_MODE;
static int radio_status = FMRADIO_OFF;
static bool in_screen = false;
#define MAX_PRESETS 64
static bool presets_loaded = false, presets_changed = false;
@ -239,22 +228,87 @@ int get_radio_status(void)
return radio_status;
}
bool in_radio_screen(void)
{
return in_screen;
}
/* secret flag for starting paused - prevents unmute */
#define FMRADIO_START_PAUSED 0x8000
void radio_start(void)
{
bool start_paused;
int mute_timeout;
if(radio_status == FMRADIO_PLAYING)
return;
start_paused = radio_status & FMRADIO_START_PAUSED;
/* clear flag before any yielding */
radio_status &= ~FMRADIO_START_PAUSED;
if(radio_status == FMRADIO_OFF)
radio_power(true);
curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ;
radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
radio_set(RADIO_FREQUENCY, curr_freq);
if(radio_status == FMRADIO_OFF)
{
radio_set(RADIO_IF_MEASUREMENT, 0);
radio_set(RADIO_SENSITIVITY, 0);
radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
mute_timeout = current_tick + 1*HZ;
}
else
{
/* paused */
mute_timeout = current_tick + 2*HZ;
}
while(!radio_get(RADIO_STEREO) && !radio_get(RADIO_TUNED))
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
/* keep radio from sounding initially */
if(!start_paused)
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
} /* radio_start */
void radio_pause(void)
{
if(radio_status == FMRADIO_PAUSED)
return;
if(radio_status == FMRADIO_OFF)
{
radio_status |= FMRADIO_START_PAUSED;
radio_start();
}
radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1);
radio_status = FMRADIO_PAUSED;
} /* radio_pause */
void radio_stop(void)
{
{
if(radio_status == FMRADIO_OFF)
return;
radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1); /* low power mode, if available */
radio_status = FMRADIO_OFF;
radio_power(false); /* status update, power off if avail. */
#ifndef SIMULATOR /* SIMULATOR. Catch FMRADIO_OFF status for the sim. */
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_TLV320
tlv320_set_monitor(false);
#endif
pcm_rec_mux(0); /* Line In */
#endif
#endif /* SIMULATOR */
}
} /* radio_stop */
bool radio_hardware_present(void)
{
@ -297,18 +351,16 @@ static int find_closest_preset(int freq)
return i;
if(diff < 0)
diff = -diff;
if(diff < min_diff)
if(diff < min_diff)
{
preset = i;
min_diff = diff;
min_diff = diff;
}
}
return preset;
}
static void remember_frequency(void)
{
global_settings.last_frequency = (curr_freq - MIN_FREQ) / FREQ_STEP;
@ -366,13 +418,15 @@ bool radio_screen(void)
#endif
bool keep_playing = false;
bool statusbar = global_settings.statusbar;
int mute_timeout = current_tick;
int button_timeout = current_tick + (2*HZ);
#ifdef HAS_BUTTONBAR
struct gui_buttonbar buttonbar;
gui_buttonbar_init(&buttonbar);
gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
#endif
/* change status to "in screen" */
in_screen = true;
/* always display status bar in radio screen for now */
global_settings.statusbar = true;
FOR_NB_SCREENS(i)
@ -396,80 +450,44 @@ bool radio_screen(void)
}
#ifndef SIMULATOR
if(radio_status == FMRADIO_OFF)
audio_stop();
#if CONFIG_CODEC != SWCODEC
if(rec_create_directory() > 0)
have_recorded = true;
#endif
if(radio_status == FMRADIO_PLAYING_OUT)
radio_status = FMRADIO_PLAYING;
else if(radio_status == FMRADIO_PAUSED_OUT)
radio_status = FMRADIO_PAUSED;
if(radio_status == FMRADIO_OFF)
audio_stop();
#if CONFIG_CODEC != SWCODEC
audio_init_recording(talk_get_bufsize());
sound_settings_apply();
/* Yes, we use the D/A for monitoring */
peak_meter_playback(true);
peak_meter_enabled = true;
if (global_settings.rec_prerecord_time)
talk_buffer_steal(); /* will use the mp3 buffer */
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
AUDIO_SRC_LINEIN, 0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
1, /* Line In */
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
#else
peak_meter_enabled = false;
#ifdef HAVE_UDA1380
uda1380_enable_recording(false);
uda1380_set_monitor(true);
#elif defined(HAVE_TLV320)
//tlv320_enable_recording(false);
tlv320_set_recvol(23, 23, AUDIO_GAIN_LINEIN); /* 0dB */
tlv320_set_monitor(true);
#endif
/* Set the input multiplexer to FM */
pcm_rec_mux(1);
#endif
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
#endif /* CONFIG_CODEC != SWCODEC */
#endif /* ndef SIMULATOR */
/* turn on radio */
#if CONFIG_CODEC == SWCODEC
rec_set_source(AUDIO_SRC_FMRADIO, (radio_status == FMRADIO_PAUSED) ?
SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
#else
if (radio_status == FMRADIO_OFF)
radio_start();
#endif
curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ;
if(radio_status == FMRADIO_OFF)
{
radio_power(true);
radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
radio_set(RADIO_FREQUENCY, curr_freq);
radio_set(RADIO_IF_MEASUREMENT, 0);
radio_set(RADIO_SENSITIVITY, 0);
radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
mute_timeout = current_tick + (1*HZ);
while( !radio_get(RADIO_STEREO)
&&!radio_get(RADIO_TUNED) )
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
}
/* I hate this thing with vehement passion (jhMikeS): */
if(num_presets == 0 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN)))
scan_presets();
@ -478,8 +496,8 @@ bool radio_screen(void)
radio_mode = RADIO_PRESET_MODE;
#ifdef HAS_BUTTONBAR
gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), str(LANG_FM_BUTTONBAR_PRESETS),
str(LANG_FM_BUTTONBAR_RECORD));
gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU),
str(LANG_FM_BUTTONBAR_PRESETS), str(LANG_FM_BUTTONBAR_RECORD));
#endif
cpu_idle_mode(true);
@ -535,7 +553,7 @@ bool radio_screen(void)
if (lastbutton != FM_STOP_PRE)
break;
#endif
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
if(audio_status() == AUDIO_STATUS_RECORD)
{
audio_stop();
@ -548,7 +566,7 @@ bool radio_screen(void)
{
if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
{
if(filepreset[0] == '\0')
if(filepreset[0] == '\0')
save_preset_list();
else
radio_save_presets();
@ -577,14 +595,13 @@ bool radio_screen(void)
#ifndef SIMULATOR
if(audio_status() == AUDIO_STATUS_RECORD)
{
audio_new_file(rec_create_filename(buf));
rec_new_file();
update_screen = true;
}
else
{
have_recorded = true;
talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(buf));
rec_record();
update_screen = true;
}
#endif
@ -604,7 +621,7 @@ bool radio_screen(void)
)
break;
#endif
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
if(audio_status() == AUDIO_STATUS_RECORD)
audio_stop();
#endif
@ -615,7 +632,7 @@ bool radio_screen(void)
{
if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
{
if(filepreset[0] == '\0')
if(filepreset[0] == '\0')
save_preset_list();
else
radio_save_presets();
@ -734,27 +751,11 @@ bool radio_screen(void)
)
break;
#endif
if(radio_status != FMRADIO_PLAYING)
{
radio_set(RADIO_SLEEP, 0);
radio_set(RADIO_FREQUENCY, curr_freq);
mute_timeout = current_tick + (2*HZ);
while( !radio_get(RADIO_STEREO)
&&!radio_get(RADIO_TUNED) )
{
if(TIME_AFTER(current_tick, mute_timeout))
break;
yield();
}
radio_set(RADIO_MUTE, 0);
radio_status = FMRADIO_PLAYING;
}
if (radio_status == FMRADIO_PLAYING)
radio_pause();
else
{
radio_set(RADIO_MUTE, 1);
radio_set(RADIO_SLEEP, 1);
radio_status = FMRADIO_PAUSED;
}
radio_start();
update_screen = true;
break;
#endif
@ -917,13 +918,17 @@ bool radio_screen(void)
if(TIME_AFTER(current_tick, timeout))
{
timeout = current_tick + HZ;
stereo = radio_get(RADIO_STEREO) &&
!global_settings.fm_force_mono;
if(stereo != last_stereo_status)
/* keep "mono" from always being displayed when paused */
if (radio_status != FMRADIO_PAUSED)
{
update_screen = true;
last_stereo_status = stereo;
stereo = radio_get(RADIO_STEREO) &&
!global_settings.fm_force_mono;
if(stereo != last_stereo_status)
{
update_screen = true;
last_stereo_status = stereo;
}
}
}
@ -952,9 +957,6 @@ bool radio_screen(void)
FOR_NB_SCREENS(i)
screens[i].puts_scroll(0, top_of_screen + 1, buf);
strcat(buf, stereo?str(LANG_CHANNEL_STEREO):
str(LANG_CHANNEL_MONO));
snprintf(buf, 128, stereo?str(LANG_CHANNEL_STEREO):
str(LANG_CHANNEL_MONO));
FOR_NB_SCREENS(i)
@ -1005,9 +1007,9 @@ bool radio_screen(void)
done = true;
}
if (TIME_AFTER(current_tick, button_timeout))
{
cpu_idle_mode(true);
}
{
cpu_idle_mode(true);
}
} /*while(!done)*/
#ifndef SIMULATOR
@ -1033,28 +1035,26 @@ bool radio_screen(void)
sound_settings_apply();
#endif /* SIMULATOR */
if(keep_playing)
{
/* Catch FMRADIO_PLAYING_OUT status for the sim. */
/* Catch FMRADIO_PLAYING status for the sim. */
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
/* Enable the Left and right A/D Converter */
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
sound_default(SOUND_RIGHT_GAIN),
AUDIO_GAIN_LINEIN);
mas_codec_writereg(6, 0x4000);
#endif
#endif
if(radio_status == FMRADIO_PAUSED)
radio_status = FMRADIO_PAUSED_OUT;
else
radio_status = FMRADIO_PLAYING_OUT;
}
else
{
radio_stop();
#if CONFIG_CODEC == SWCODEC
peak_meter_enabled = true;
rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#else
radio_stop();
#endif
}
@ -1062,9 +1062,11 @@ bool radio_screen(void)
/* restore status bar settings */
global_settings.statusbar = statusbar;
in_screen = false;
return have_recorded;
}
} /* radio_screen */
void radio_save_presets(void)
{
@ -1106,16 +1108,16 @@ void radio_load_presets(char *filename)
/* No Preset in configuration. */
if(filename[0] == '\0')
{
{
filepreset[0] = '\0';
return;
}
}
/* Temporary preset, loaded until player shuts down. */
else if(filename[0] == '/')
strncpy(filepreset, filename, sizeof(filepreset));
/* Preset from default directory. */
else
snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
FMPRESET_PATH, filename);
fd = open(filepreset, O_RDONLY);
@ -1466,30 +1468,6 @@ bool handle_radio_presets(void)
return reload_dir;
}
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
static bool fm_recording_settings(void)
{
bool ret;
ret = recording_menu(true);
if(!ret)
{
if (global_settings.rec_prerecord_time)
talk_buffer_steal(); /* will use the mp3 buffer */
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
1, /* Line In */
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
}
return ret;
}
#endif
#endif
char monomode_menu_string[32];
static void create_monomode_menu(void)
@ -1628,6 +1606,55 @@ int radio_menu_cb(int key, int m)
return key;
}
#ifndef SIMULATOR
#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
static bool fm_recording_screen(void)
{
bool ret;
#ifdef HAVE_FMRADIO_IN
/* switch recording source to FMRADIO for the duration */
int rec_source = global_settings.rec_source;
global_settings.rec_source = AUDIO_SRC_FMRADIO;
/* clearing queue seems to cure a spontaneous abort during record */
while (button_get(false) != BUTTON_NONE);
#endif
ret = recording_screen(true);
#ifdef HAVE_FMRADIO_IN
/* safe to reset as changing sources is prohibited here */
global_settings.rec_source = rec_source;
#endif
return ret;
}
static bool fm_recording_settings(void)
{
bool ret = recording_menu(true);
if (!ret)
{
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
#if CONFIG_CODEC == SWCODEC
AUDIO_SRC_FMRADIO, SRCF_FMRADIO_PLAYING,
#else
AUDIO_SRC_LINEIN, 0,
#endif
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
}
return ret;
}
#endif
#endif /* SIMULATOR */
/* main menu of the radio screen */
bool radio_menu(void)
{
@ -1637,24 +1664,27 @@ bool radio_menu(void)
static const struct menu_item items[] = {
/* Add functions not accessible via buttons */
#ifndef FM_PRESET
{ ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets },
{ ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets },
#endif
#ifndef FM_PRESET_ADD
{ ID2P(LANG_FM_ADD_PRESET) , radio_add_preset },
{ ID2P(LANG_FM_ADD_PRESET) , radio_add_preset },
#endif
{ ID2P(LANG_FM_PRESET_LOAD) , load_preset_list },
{ ID2P(LANG_FM_PRESET_SAVE) , save_preset_list },
{ ID2P(LANG_FM_PRESET_CLEAR) , clear_preset_list },
{ ID2P(LANG_FM_PRESET_LOAD) , load_preset_list },
{ ID2P(LANG_FM_PRESET_SAVE) , save_preset_list },
{ ID2P(LANG_FM_PRESET_CLEAR) , clear_preset_list },
{ monomode_menu_string , toggle_mono_mode },
{ monomode_menu_string , toggle_mono_mode },
#ifndef FM_MODE
{ radiomode_menu_string , toggle_radio_mode },
{ radiomode_menu_string , toggle_radio_mode },
#endif
{ ID2P(LANG_SOUND_SETTINGS) , sound_menu },
#if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
{ ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings},
{ ID2P(LANG_SOUND_SETTINGS) , sound_menu },
#ifndef SIMULATOR
#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
{ ID2P(LANG_RECORDING_MENU) , fm_recording_screen },
{ ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings },
#endif
{ ID2P(LANG_FM_SCAN_PRESETS) , scan_presets },
#endif
{ ID2P(LANG_FM_SCAN_PRESETS) , scan_presets },
};
create_monomode_menu();

View file

@ -20,19 +20,19 @@
#define RADIO_H
#define FMPRESET_PATH ROCKBOX_DIR "/fmpresets"
#define FMRADIO_OFF 0
#define FMRADIO_PLAYING 1
#define FMRADIO_PLAYING_OUT 2
#define FMRADIO_PAUSED 3
#define FMRADIO_PAUSED_OUT 4
#ifndef FMRADIO_H
#include "fmradio.h"
#endif
#ifdef CONFIG_TUNER
void radio_load_presets(char *filename);
void radio_init(void);
bool radio_screen(void);
void radio_start(void);
void radio_pause(void);
void radio_stop(void);
bool radio_hardware_present(void);
int get_radio_status(void);
bool in_radio_screen(void);
#define MAX_FMPRESET_LEN 27

View file

@ -24,12 +24,14 @@
#include <stdlib.h>
#include "system.h"
#include "power.h"
#include "lcd.h"
#include "led.h"
#include "mpeg.h"
#include "audio.h"
#if CONFIG_CODEC == SWCODEC
#include "pcm_record.h"
#include "playback.h"
#endif
#ifdef HAVE_UDA1380
#include "uda1380.h"
@ -37,7 +39,7 @@
#ifdef HAVE_TLV320
#include "tlv320.h"
#endif
#include "recording.h"
#include "mp3_playback.h"
#include "mas.h"
#include "button.h"
@ -66,6 +68,7 @@
#include "splash.h"
#include "screen_access.h"
#include "action.h"
#include "radio.h"
#ifdef HAVE_RECORDING
#define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1)
@ -73,21 +76,6 @@
bool f2_rec_screen(void);
bool f3_rec_screen(void);
#define SOURCE_MIC 0
#define SOURCE_LINE 1
#ifdef HAVE_SPDIF_IN
#define SOURCE_SPDIF 2
#define MAX_SOURCE SOURCE_SPDIF
#else
#define MAX_SOURCE SOURCE_LINE
#endif
#if CONFIG_CODEC == SWCODEC
#define REC_FILE_ENDING ".wav"
#else
#define REC_FILE_ENDING ".mp3"
#endif
#define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */
int screen_update = NB_SCREENS;
@ -102,6 +90,19 @@ const char* const freq_str[6] =
"16kHz"
};
#if CONFIG_CODEC == SWCODEC
#define REC_ENCODER_ID(q) \
rec_quality_info_afmt[q]
#define REC_QUALITY_LABEL(q) \
(audio_formats[REC_ENCODER_ID(q)].label)
#define REC_FILE_ENDING(q) \
(audio_formats[REC_ENCODER_ID(q)].ext)
#else
/* default record file extension for HWCODEC */
#define REC_QUALITY_LABEL(q) "MP3"
#define REC_FILE_ENDING(q) ".mp3"
#endif
#ifdef HAVE_AGC
/* Timing counters:
* peak_time is incremented every 0.2s, every 2nd run of record screen loop.
@ -161,13 +162,14 @@ static short agc_maxgain;
static void set_gain(void)
{
if(global_settings.rec_source == SOURCE_MIC)
if(global_settings.rec_source == AUDIO_SRC_MIC)
{
audio_set_recording_gain(global_settings.rec_mic_gain,
0, AUDIO_GAIN_MIC);
}
else
{
/* AUDIO_SRC_LINEIN, AUDIO_SRC_SPDIF, AUDIO_SRC_FMRADIO */
audio_set_recording_gain(global_settings.rec_left_gain,
global_settings.rec_right_gain,
AUDIO_GAIN_LINEIN);
@ -217,12 +219,16 @@ bool agc_gain_is_max(bool left, bool right)
if (agc_preset == 0)
return false;
if (global_settings.rec_source == SOURCE_LINE)
switch (global_settings.rec_source)
{
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
gain_current_l = global_settings.rec_left_gain;
gain_current_r = global_settings.rec_right_gain;
} else
{
break;
default:
gain_current_l = global_settings.rec_mic_gain;
gain_current_r = global_settings.rec_mic_gain;
}
@ -235,13 +241,16 @@ void change_recording_gain(bool increment, bool left, bool right)
{
int factor = (increment ? 1 : -1);
if (global_settings.rec_source == SOURCE_LINE)
switch (global_settings.rec_source)
{
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
if(left) global_settings.rec_left_gain += factor;
if (right) global_settings.rec_right_gain += factor;
}
else
{
break;
default:
global_settings.rec_mic_gain += factor;
}
}
@ -443,12 +452,15 @@ void adjust_cursor(void)
#ifdef HAVE_AGC
switch(global_settings.rec_source)
{
case SOURCE_MIC:
case AUDIO_SRC_MIC:
if(cursor == 2)
cursor = 4;
else if(cursor == 3)
cursor = 1;
case SOURCE_LINE:
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
max_cursor = 5;
break;
default:
@ -458,10 +470,13 @@ void adjust_cursor(void)
#else
switch(global_settings.rec_source)
{
case SOURCE_MIC:
case AUDIO_SRC_MIC:
max_cursor = 1;
break;
case SOURCE_LINE:
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
max_cursor = 3;
break;
default:
@ -481,10 +496,13 @@ char *rec_create_filename(char *buffer)
else
strncpy(buffer, rec_base_directory, MAX_PATH);
#ifdef CONFIG_RTC
create_datetime_filename(buffer, buffer, "R", REC_FILE_ENDING);
create_datetime_filename(buffer, buffer, "R",
REC_FILE_ENDING(global_settings.rec_quality));
#else
create_numbered_filename(buffer, buffer, "rec_", REC_FILE_ENDING, 4);
create_numbered_filename(buffer, buffer, "rec_",
REC_FILE_ENDING(global_settings.rec_quality), 4);
#endif
return buffer;
}
@ -515,8 +533,190 @@ int rec_create_directory(void)
return 0;
}
#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR)
/**
* Selects an audio source for recording or playback
* powers/unpowers related devices.
* Here because it calls app code and used only for HAVE_RECORDING atm.
* Would like it in pcm_record.c.
*/
#if defined(HAVE_UDA1380)
#define ac_disable_recording uda1380_disable_recording
#define ac_enable_recording uda1380_enable_recording
#define ac_set_monitor uda1380_set_monitor
#elif defined(HAVE_TLV320)
#define ac_disable_recording tlv320_disable_recording
#define ac_enable_recording tlv320_enable_recording
#define ac_set_monitor tlv320_set_monitor
#endif
void rec_set_source(int source, int flags)
{
/* Prevent pops from unneeded switching */
static int last_source = AUDIO_SRC_PLAYBACK;
#ifdef HAVE_TLV320
static bool last_recording = false;
#endif
bool recording = flags & SRCF_RECORDING;
/* Default to peakmeter record. */
bool pm_playback = false;
bool pm_enabled = true;
/** Do power up/down of associated device(s) **/
#ifdef HAVE_SPDIF_IN
if ((source == AUDIO_SRC_SPDIF) != (source == last_source))
cpu_boost(source == AUDIO_SRC_SPDIF);
#ifdef HAVE_SPDIF_POWER
/* Check if S/PDIF output power should be switched off or on. NOTE: assumes
both optical in and out is controlled by the same power source, which is
the case on H1x0. */
spdif_power_enable((source == AUDIO_SRC_SPDIF) ||
global_settings.spdif_enable);
#endif
#endif
#ifdef CONFIG_TUNER
/* Switch radio off or on per source and flags. */
if (source != AUDIO_SRC_FMRADIO)
radio_stop();
else if (flags & SRCF_FMRADIO_PAUSED)
radio_pause();
else
radio_start();
#endif
switch (source)
{
default: /* playback - no recording */
pm_playback = true;
if (source == last_source)
break;
ac_disable_recording();
ac_set_monitor(false);
pcm_rec_mux(0); /* line in */
break;
case AUDIO_SRC_MIC: /* recording only */
if (source == last_source)
break;
ac_enable_recording(true); /* source mic */
pcm_rec_mux(0); /* line in */
break;
case AUDIO_SRC_LINEIN: /* recording only */
if (source == last_source)
break;
pcm_rec_mux(0); /* line in */
ac_enable_recording(false); /* source line */
break;
#ifdef HAVE_SPDIF_IN
case AUDIO_SRC_SPDIF: /* recording only */
if (recording)
{
/* This was originally done in audio_set_recording_options only */
#ifdef HAVE_SPDIF_POWER
EBU1CONFIG = global_settings.spdif_enable ? (1 << 2) : 0;
/* Input source is EBUin1, Feed-through monitoring if desired */
#else
EBU1CONFIG = (1 << 2);
/* Input source is EBUin1, Feed-through monitoring */
#endif
}
if (source != last_source)
uda1380_disable_recording();
break;
#endif /* HAVE_SPDIF_IN */
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
if (!recording)
{
audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
pm_playback = true;
pm_enabled = false;
}
pcm_rec_mux(1); /* fm radio */
#ifdef HAVE_UDA1380
if (source == last_source)
break;
/* I2S recording and playback */
uda1380_enable_recording(false); /* source line */
uda1380_set_monitor(true);
#endif
#ifdef HAVE_TLV320
/* I2S recording and analog playback */
if (source == last_source && recording == last_recording)
break;
last_recording = recording;
if (recording)
tlv320_enable_recording(false); /* source line */
else
{
tlv320_disable_recording();
tlv320_set_monitor(true); /* analog bypass */
}
#endif
break;
/* #elif defined(CONFIG_TUNER) */
/* Have radio but cannot record it */
/* case AUDIO_SRC_FMRADIO: */
/* break; */
#endif /* HAVE_FMRADIO_IN */
} /* end switch */
peak_meter_playback(pm_playback);
peak_meter_enabled = pm_enabled;
last_source = source;
} /* rec_set_source */
#endif /* CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) */
/* steal the mp3 buffer then actually set options */
void rec_set_recording_options(int frequency, int quality,
int source, int source_flags,
int channel_mode, bool editable,
int prerecord_time)
{
#if CONFIG_CODEC != SWCODEC
if (global_settings.rec_prerecord_time)
#endif
talk_buffer_steal(); /* will use the mp3 buffer */
#if CONFIG_CODEC == SWCODEC
rec_set_source(source, source_flags | SRCF_RECORDING);
#else
(void)source_flags;
#endif
audio_set_recording_options(frequency, quality, source,
channel_mode, editable, prerecord_time);
}
static char path_buffer[MAX_PATH];
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void)
{
talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer));
}
/* creates unique filename and starts recording */
void rec_new_file(void)
{
audio_new_file(rec_create_filename(path_buffer));
}
/* used in trigger_listerner and recording_screen */
static unsigned int last_seconds = 0;
@ -533,16 +733,16 @@ static void trigger_listener(int trigger_status)
if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD)
{
talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer));
/* give control to mpeg thread so that it can start recording*/
rec_record();
/* give control to mpeg thread so that it can start
recording */
yield(); yield(); yield();
}
/* if we're already recording this is a retrigger */
else
{
audio_new_file(rec_create_filename(path_buffer));
rec_new_file();
/* tell recording_screen to reset the time */
last_seconds = 0;
}
@ -563,10 +763,9 @@ static void trigger_listener(int trigger_status)
}
}
bool recording_screen(void)
bool recording_screen(bool no_source)
{
long button;
long lastbutton = BUTTON_NONE;
bool done = false;
char buf[32];
char buf2[32];
@ -575,11 +774,19 @@ bool recording_screen(void)
bool have_recorded = false;
unsigned int seconds;
int hours, minutes;
char path_buffer[MAX_PATH];
char filename[13];
bool been_in_usb_mode = false;
int last_audio_stat = -1;
int audio_stat;
#ifdef HAVE_FMRADIO_IN
/* Radio is left on if:
* 1) Is was on at the start and the initial source is FM Radio
* 2) 1) and the source was never changed to something else
*/
int radio_status = (global_settings.rec_source != AUDIO_SRC_FMRADIO) ?
FMRADIO_OFF : get_radio_status();
#endif
int talk_menu = global_settings.talk_menu;
#if CONFIG_LED == LED_REAL
bool led_state = false;
int led_countdown = 2;
@ -608,6 +815,18 @@ bool recording_screen(void)
ata_set_led_enabled(false);
#endif
#if CONFIG_CODEC == SWCODEC
audio_stop();
voice_stop();
/* recording_menu gets messed up: so reset talk_menu */
talk_menu = global_settings.talk_menu;
global_settings.talk_menu = 0;
#else
/* Yes, we use the D/A for monitoring */
peak_meter_enabled = true;
peak_meter_playback(true);
#endif
#ifndef SIMULATOR
audio_init_recording(talk_get_bufsize());
#else
@ -616,44 +835,19 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume);
#if CONFIG_CODEC == SWCODEC
audio_stop();
/* Set peak meter to recording mode */
peak_meter_playback(false);
#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
if (global_settings.rec_source == SOURCE_SPDIF)
cpu_boost(true);
#endif
#else
/* Yes, we use the D/A for monitoring */
peak_meter_playback(true);
#endif
peak_meter_enabled = true;
#ifdef HAVE_AGC
peak_meter_get_peakhold(&peak_l, &peak_r);
#endif
#if CONFIG_CODEC != SWCODEC
if (global_settings.rec_prerecord_time)
#endif
talk_buffer_steal(); /* will use the mp3 buffer */
#if defined(HAVE_SPDIF_POWER) && !defined(SIMULATOR)
/* Tell recording whether we want S/PDIF power enabled at all times */
audio_set_spdif_power_setting(global_settings.spdif_enable);
#endif
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain();
settings_apply_trigger();
#ifdef HAVE_AGC
@ -663,7 +857,7 @@ bool recording_screen(void)
agc_preset_str[3] = str(LANG_AGC_DJSET);
agc_preset_str[4] = str(LANG_AGC_MEDIUM);
agc_preset_str[5] = str(LANG_AGC_VOICE);
if (global_settings.rec_source == SOURCE_MIC) {
if (global_settings.rec_source == AUDIO_SRC_MIC) {
agc_preset = global_settings.rec_agc_preset_mic;
agc_maxgain = global_settings.rec_agc_maxgain_mic;
}
@ -697,11 +891,7 @@ bool recording_screen(void)
while(!done)
{
#if CONFIG_CODEC == SWCODEC
audio_stat = pcm_rec_status();
#else
audio_stat = audio_status();
#endif
#if CONFIG_LED == LED_REAL
@ -794,8 +984,8 @@ bool recording_screen(void)
}
else
{
peak_meter_playback(true);
#if CONFIG_CODEC != SWCODEC
peak_meter_playback(true);
peak_meter_enabled = false;
#endif
done = true;
@ -815,14 +1005,13 @@ bool recording_screen(void)
/* manual recording */
have_recorded = true;
talk_buffer_steal(); /* we use the mp3 buffer */
audio_record(rec_create_filename(path_buffer));
rec_record();
last_seconds = 0;
if (global_settings.talk_menu)
if (talk_menu)
{ /* no voice possible here, but a beep */
audio_beep(HZ/2); /* longer beep on start */
}
}
/* this is triggered recording */
else
{
@ -838,7 +1027,7 @@ bool recording_screen(void)
/*if new file button pressed, start new file */
if (button == ACTION_REC_NEWFILE)
{
audio_new_file(rec_create_filename(path_buffer));
rec_new_file();
last_seconds = 0;
}
else
@ -847,7 +1036,7 @@ bool recording_screen(void)
if(audio_stat & AUDIO_STATUS_PAUSE)
{
audio_resume_recording();
if (global_settings.talk_menu)
if (talk_menu)
{ /* no voice possible here, but a beep */
audio_beep(HZ/4); /* short beep on resume */
}
@ -883,7 +1072,7 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume);
break;
case 1:
if(global_settings.rec_source == SOURCE_MIC)
if(global_settings.rec_source == AUDIO_SRC_MIC)
{
if(global_settings.rec_mic_gain <
sound_max(SOUND_MIC_GAIN))
@ -913,7 +1102,7 @@ bool recording_screen(void)
case 4:
agc_preset = MIN(agc_preset + 1, AGC_MODE_SIZE);
agc_enable = (agc_preset != 0);
if (global_settings.rec_source == SOURCE_MIC) {
if (global_settings.rec_source == AUDIO_SRC_MIC) {
global_settings.rec_agc_preset_mic = agc_preset;
agc_maxgain = global_settings.rec_agc_maxgain_mic;
} else {
@ -922,7 +1111,7 @@ bool recording_screen(void)
}
break;
case 5:
if (global_settings.rec_source == SOURCE_MIC)
if (global_settings.rec_source == AUDIO_SRC_MIC)
{
agc_maxgain = MIN(agc_maxgain + 1,
sound_max(SOUND_MIC_GAIN));
@ -951,7 +1140,7 @@ bool recording_screen(void)
sound_set_volume(global_settings.volume);
break;
case 1:
if(global_settings.rec_source == SOURCE_MIC)
if(global_settings.rec_source == AUDIO_SRC_MIC)
{
if(global_settings.rec_mic_gain >
sound_min(SOUND_MIC_GAIN))
@ -981,7 +1170,7 @@ bool recording_screen(void)
case 4:
agc_preset = MAX(agc_preset - 1, 0);
agc_enable = (agc_preset != 0);
if (global_settings.rec_source == SOURCE_MIC) {
if (global_settings.rec_source == AUDIO_SRC_MIC) {
global_settings.rec_agc_preset_mic = agc_preset;
agc_maxgain = global_settings.rec_agc_maxgain_mic;
} else {
@ -990,7 +1179,7 @@ bool recording_screen(void)
}
break;
case 5:
if (global_settings.rec_source == SOURCE_MIC)
if (global_settings.rec_source == AUDIO_SRC_MIC)
{
agc_maxgain = MAX(agc_maxgain - 1,
sound_min(SOUND_MIC_GAIN));
@ -1012,49 +1201,73 @@ bool recording_screen(void)
case ACTION_STD_MENU:
if(audio_stat != AUDIO_STATUS_RECORD)
{
#ifdef HAVE_FMRADIO_IN
const int prev_rec_source = global_settings.rec_source;
#endif
#if CONFIG_LED == LED_REAL
/* led is restored at begin of loop / end of function */
led(false);
#endif
if (recording_menu(false))
if (recording_menu(no_source))
{
return SYS_USB_CONNECTED;
}
settings_save();
#if CONFIG_CODEC != SWCODEC
if (global_settings.rec_prerecord_time)
done = true;
been_in_usb_mode = true;
#ifdef HAVE_FMRADIO_IN
radio_status = FMRADIO_OFF;
#endif
talk_buffer_steal(); /* will use the mp3 buffer */
}
else
{
settings_save();
#ifdef HAVE_FMRADIO_IN
/* If input changes away from FM Radio, radio will
remain off when recording screen closes. */
if (global_settings.rec_source != prev_rec_source
&& prev_rec_source == AUDIO_SRC_FMRADIO)
radio_status = FMRADIO_OFF;
#endif
#if CONFIG_CODEC == SWCODEC
/* reinit after submenu exit */
audio_close_recording();
audio_init_recording(talk_get_bufsize());
#endif
rec_set_recording_options(
global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
#ifdef HAVE_AGC
if (global_settings.rec_source == SOURCE_MIC) {
agc_preset = global_settings.rec_agc_preset_mic;
agc_maxgain = global_settings.rec_agc_maxgain_mic;
}
else {
agc_preset = global_settings.rec_agc_preset_line;
agc_maxgain = global_settings.rec_agc_maxgain_line;
}
if (global_settings.rec_source == AUDIO_SRC_MIC) {
agc_preset = global_settings.rec_agc_preset_mic;
agc_maxgain = global_settings.rec_agc_maxgain_mic;
}
else {
agc_preset = global_settings.rec_agc_preset_line;
agc_maxgain = global_settings.rec_agc_maxgain_line;
}
#endif
adjust_cursor();
set_gain();
update_countdown = 1; /* Update immediately */
adjust_cursor();
set_gain();
update_countdown = 1; /* Update immediately */
FOR_NB_SCREENS(i)
{
screens[i].setfont(FONT_SYSFIXED);
screens[i].setmargins(global_settings.invert_cursor ? 0 : w, 8);
FOR_NB_SCREENS(i)
{
screens[i].setfont(FONT_SYSFIXED);
screens[i].setmargins(
global_settings.invert_cursor ? 0 : w, 8);
}
}
}
break;
#if CONFIG_KEYPAD == RECORDER_PAD
case ACTION_REC_F2:
if(audio_stat != AUDIO_STATUS_RECORD)
@ -1076,7 +1289,7 @@ bool recording_screen(void)
case ACTION_REC_F3:
if(audio_stat & AUDIO_STATUS_RECORD)
{
audio_new_file(rec_create_filename(path_buffer));
rec_new_file();
last_seconds = 0;
}
else
@ -1097,7 +1310,7 @@ bool recording_screen(void)
}
}
break;
#endif
#endif /* CONFIG_KEYPAD == RECORDER_PAD */
case SYS_USB_CONNECTED:
/* Only accept USB connection when not recording */
@ -1106,6 +1319,9 @@ bool recording_screen(void)
default_event_handler(SYS_USB_CONNECTED);
done = true;
been_in_usb_mode = true;
#ifdef HAVE_FMRADIO_IN
radio_status = FMRADIO_OFF;
#endif
}
break;
@ -1113,8 +1329,6 @@ bool recording_screen(void)
default_event_handler(button);
break;
}
if (button != BUTTON_NONE)
lastbutton = button;
#ifdef HAVE_AGC
peak_read = !peak_read;
@ -1230,7 +1444,7 @@ bool recording_screen(void)
if (!(global_settings.rec_split_type)
|| (num_recorded_bytes >= MAX_FILE_SIZE))
{
audio_new_file(rec_create_filename(path_buffer));
rec_new_file();
last_seconds = 0;
}
else
@ -1259,8 +1473,9 @@ bool recording_screen(void)
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 2, buf);
}
if(global_settings.rec_source == SOURCE_MIC)
{
if(global_settings.rec_source == AUDIO_SRC_MIC)
{
/* Draw MIC recording gain */
snprintf(buf, 32, "%s:%s", str(LANG_SYSFONT_RECORDING_GAIN),
fmt_gain(SOUND_MIC_GAIN,
global_settings.rec_mic_gain,
@ -1278,8 +1493,13 @@ bool recording_screen(void)
PM_HEIGHT + 3, buf);
}
}
else if(global_settings.rec_source == SOURCE_LINE)
else if(global_settings.rec_source == AUDIO_SRC_LINEIN
#ifdef HAVE_FMRADIO_IN
|| global_settings.rec_source == AUDIO_SRC_FMRADIO
#endif
)
{
/* Draw LINE or FMRADIO recording gain */
snprintf(buf, 32, "%s:%s",
str(LANG_SYSFONT_RECORDING_LEFT),
fmt_gain(SOUND_LEFT_GAIN,
@ -1319,14 +1539,23 @@ bool recording_screen(void)
FOR_NB_SCREENS(i)
{
if (global_settings.rec_source == SOURCE_LINE)
line[i] = 5;
else if (global_settings.rec_source == SOURCE_MIC)
line[i] = 4;
#ifdef HAVE_SPDIF_IN
else if (global_settings.rec_source == SOURCE_SPDIF)
line[i] = 3;
switch (global_settings.rec_source)
{
case AUDIO_SRC_LINEIN:
#ifdef HAVE_FMRADIO_IN
case AUDIO_SRC_FMRADIO:
#endif
line[i] = 5;
break;
case AUDIO_SRC_MIC:
line[i] = 4;
break;
#ifdef HAVE_SPDIF_IN
case AUDIO_SRC_SPDIF:
line[i] = 3;
break;
#endif
} /* end switch */
#ifdef HAVE_AGC
if (screens[i].height < h * (2 + filename_offset[i] + PM_HEIGHT + line[i]))
{
@ -1358,7 +1587,7 @@ bool recording_screen(void)
snprintf(buf, 32, "%s: %s",
str(LANG_RECORDING_AGC_PRESET),
agc_preset_str[agc_preset]);
else if (global_settings.rec_source == SOURCE_MIC)
else if (global_settings.rec_source == AUDIO_SRC_MIC)
snprintf(buf, 32, "%s: %s%s",
str(LANG_RECORDING_AGC_PRESET),
agc_preset_str[agc_preset],
@ -1382,8 +1611,12 @@ bool recording_screen(void)
screens[i].puts_style_offset(0, filename_offset[i] +
PM_HEIGHT + line[i], buf, STYLE_INVERT,0);
}
else if ((global_settings.rec_source == SOURCE_MIC)
|| (global_settings.rec_source == SOURCE_LINE))
else if (global_settings.rec_source == AUDIO_SRC_MIC
|| global_settings.rec_source == AUDIO_SRC_LINEIN
#ifdef HAVE_FMRADIO_IN
|| global_settings.rec_source == AUDIO_SRC_FMRADIO
#endif
)
{
for(i = 0; i < screen_update; i++) {
if (display_agc[i]) {
@ -1393,7 +1626,7 @@ bool recording_screen(void)
}
}
if (global_settings.rec_source == SOURCE_MIC)
if (global_settings.rec_source == AUDIO_SRC_MIC)
{
if(agc_maxgain < (global_settings.rec_mic_gain))
change_recording_gain(false, true, true);
@ -1418,7 +1651,7 @@ bool recording_screen(void)
filename_offset[i] +
PM_HEIGHT + 3, true);
if(global_settings.rec_source != SOURCE_MIC)
if(global_settings.rec_source != AUDIO_SRC_MIC)
{
for(i = 0; i < screen_update; i++)
screen_put_cursorxy(&screens[i], 0,
@ -1456,14 +1689,14 @@ bool recording_screen(void)
}
/* Can't measure S/PDIF sample rate on Archos yet */
#if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
if (global_settings.rec_source == SOURCE_SPDIF)
if (global_settings.rec_source == AUDIO_SRC_SPDIF)
snprintf(spdif_sfreq, 8, "%dHz", audio_get_spdif_sample_rate());
#else
(void)spdif_sfreq;
#endif
snprintf(buf, 32, "%s %s",
#if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
global_settings.rec_source == SOURCE_SPDIF ?
global_settings.rec_source == AUDIO_SRC_SPDIF ?
spdif_sfreq :
#endif
freq_str[global_settings.rec_frequency],
@ -1473,8 +1706,8 @@ bool recording_screen(void)
for(i = 0; i < screen_update; i++) {
#ifdef HAVE_AGC
if ((global_settings.rec_source == SOURCE_MIC)
|| (global_settings.rec_source == SOURCE_LINE))
if ((global_settings.rec_source == AUDIO_SRC_MIC)
|| (global_settings.rec_source == AUDIO_SRC_LINEIN))
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + line[i] + 1, buf);
else
#endif
@ -1484,6 +1717,14 @@ bool recording_screen(void)
#ifdef HAVE_AGC
hist_time++;
#endif
#if CONFIG_CODEC == SWCODEC
snprintf(buf, 32, "%s",
REC_QUALITY_LABEL(global_settings.rec_quality));
for(i = 0; i < screen_update; i++)
screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 6, buf);
#endif
for(i = 0; i < screen_update; i++)
{
gui_statusbar_draw(&(statusbars.statusbars[i]), true);
@ -1506,7 +1747,7 @@ bool recording_screen(void)
{
done = true;
}
}
} /* end while(!done) */
#if CONFIG_CODEC == SWCODEC
@ -1531,18 +1772,26 @@ bool recording_screen(void)
}
}
#if CONFIG_CODEC == SWCODEC
#if CONFIG_CODEC == SWCODEC
audio_stop_recording();
audio_close_recording();
#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
if (global_settings.rec_source == SOURCE_SPDIF)
cpu_boost(false);
#ifdef HAVE_FMRADIO_IN
if (radio_status != FMRADIO_OFF)
/* Restore radio playback - radio_status should be unchanged if started
through fm radio screen (barring usb connect) */
rec_set_source(AUDIO_SRC_FMRADIO, (radio_status & FMRADIO_PAUSED) ?
SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
else
#endif
/* Go back to playback mode */
rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#else
/* restore talk_menu setting */
global_settings.talk_menu = talk_menu;
#else /* !SWCODEC */
audio_init_playback();
#endif
#endif /* CONFIG_CODEC == SWCODEC */
/* make sure the trigger is really turned off */
peak_meter_trigger(false);
@ -1560,7 +1809,7 @@ bool recording_screen(void)
ata_set_led_enabled(true);
#endif
return been_in_usb_mode;
}
} /* recording_screen */
#if CONFIG_KEYPAD == RECORDER_PAD
bool f2_rec_screen(void)
@ -1680,15 +1929,13 @@ bool f2_rec_screen(void)
}
}
if (global_settings.rec_prerecord_time)
talk_buffer_steal(); /* will use the mp3 buffer */
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain();
@ -1760,7 +2007,7 @@ bool f3_rec_screen(void)
case BUTTON_LEFT:
case BUTTON_F3 | BUTTON_LEFT:
global_settings.rec_source++;
if(global_settings.rec_source > MAX_SOURCE)
if(global_settings.rec_source > AUDIO_SRC_MAX)
global_settings.rec_source = 0;
used = true;
break;
@ -1782,16 +2029,13 @@ bool f3_rec_screen(void)
}
}
if (global_settings.rec_prerecord_time)
talk_buffer_steal(); /* will use the mp3 buffer */
audio_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
rec_set_recording_options(global_settings.rec_frequency,
global_settings.rec_quality,
global_settings.rec_source,
0,
global_settings.rec_channels,
global_settings.rec_editable,
global_settings.rec_prerecord_time);
set_gain();
@ -1801,7 +2045,7 @@ bool f3_rec_screen(void)
return false;
}
#endif /* #ifdef RECORDER_PAD */
#endif /* CONFIG_KEYPAD == RECORDER_PAD */
#if CONFIG_CODEC == SWCODEC
void audio_beep(int duration)
@ -1831,6 +2075,14 @@ unsigned long audio_num_recorded_bytes(void)
return 5 * 1024 * 1024;
}
#if CONFIG_CODEC == SWCODEC
void rec_set_source(int source, int flags)
{
source = source;
flags = flags;
}
#endif
void audio_set_recording_options(int frequency, int quality,
int source, int channel_mode,
bool editable, int prerecord_time)

View file

@ -19,8 +19,33 @@
#ifndef RECORDING_H
#define RECORDING_H
bool recording_screen(void);
bool recording_screen(bool no_source);
char *rec_create_filename(char *buf);
int rec_create_directory(void);
#if CONFIG_CODEC == SWCODEC
/* selects an audio source for recording or playback */
#define SRCF_PLAYBACK 0x0000 /* default */
#define SRCF_RECORDING 0x1000
#ifdef CONFIG_TUNER
/* for AUDIO_SRC_FMRADIO */
#define SRCF_FMRADIO_PLAYING 0x0000 /* default */
#define SRCF_FMRADIO_PAUSED 0x2000
#endif
void rec_set_source(int source, int flags);
#endif /* CONFIG_CODEC == SW_CODEC */
/* steals mp3 buffer, sets source and then options */
/* SRCF_RECORDING is implied */
void rec_set_recording_options(int frequency, int quality,
int source, int source_flags,
int channel_mode, bool editable,
int prerecord_time);
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void);
/* creates unique filename and starts recording */
void rec_new_file(void);
#endif

View file

@ -92,7 +92,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
#include "dsp.h"
#endif
#define CONFIG_BLOCK_VERSION 50
#define CONFIG_BLOCK_VERSION 51
#define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44
@ -473,11 +473,21 @@ static const struct bit_entry hd_bits[] =
{1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" },
{1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" },
#ifdef HAVE_SPDIF_IN
{2, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line,spdif" },
{
#if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
2,
#else
{1, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line" },
1,
#endif
S_O(rec_source), 0 /* 0=mic */, "rec source",
"mic,line"
#ifdef HAVE_SPDIF_IN
",spdif"
#endif
#ifdef HAVE_FMRADIO_IN
",fmradio"
#endif
},
{5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
{1, S_O(rec_directory), 0, /* rec_base_directory */
"rec directory", REC_BASE_DIR ",current" },
@ -490,14 +500,21 @@ static const struct bit_entry hd_bits[] =
{4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */
{3, S_O(rec_frequency), 0, /* 0=44.1kHz */
"rec frequency", "44,48,32,22,24,16" },
{3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL },
{1, S_O(rec_editable), false, "editable recordings", off_on },
{3, S_O(rec_quality), 5, "rec quality", NULL },
#elif defined(HAVE_UDA1380)
#elif defined(HAVE_UDA1380) || defined(HAVE_TLV320)
#ifdef HAVE_UDA1380
{8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
#endif
#ifdef HAVE_TLV320
/* TLV320 only has no mic boost or 20db mic boost */
{1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */
#endif
{8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */
{8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */
{3, S_O(rec_frequency), 0, /* 0=44.1kHz */
"rec frequency", "44,48,32,22,24,16" },
{4, S_O(rec_quality), 4 /* MP3 L3 192 kBit/s */, "rec quality", NULL },
#endif
/* values for the trigger */

View file

@ -42,6 +42,7 @@
#define BACKDROP_DIR ROCKBOX_DIR"/backdrops"
#define REC_BASE_DIR "/recordings"
#define EQS_DIR ROCKBOX_DIR "/eqs"
#define CODECS_DIR "/codecs"
#define MAX_FILENAME 20

View file

@ -39,6 +39,12 @@
#include "talk.h"
#include "misc.h"
#include "sound.h"
#ifdef HAVE_RECORDING
#include "audio.h"
#ifdef CONFIG_TUNER
#include "radio.h"
#endif
#endif
#if CONFIG_CODEC == MAS3587F
#include "peakmeter.h"
#include "mas.h"
@ -290,19 +296,68 @@ static bool avc(void)
#ifdef HAVE_RECORDING
static bool recsource(void)
{
static const struct opt_items names[] = {
int n_opts = AUDIO_NUM_SOURCES;
struct opt_items names[AUDIO_NUM_SOURCES] = {
{ STR(LANG_RECORDING_SRC_MIC) },
{ STR(LANG_RECORDING_SRC_LINE) },
#ifdef HAVE_SPDIF_IN
{ STR(LANG_RECORDING_SRC_DIGITAL) },
#endif
};
/* caveat: assumes it's the last item! */
#ifdef HAVE_FMRADIO_IN
if (radio_hardware_present())
{
names[AUDIO_SRC_FMRADIO].string = ID2P(LANG_FM_RADIO);
names[AUDIO_SRC_FMRADIO].voice_id = LANG_FM_RADIO;
}
else
n_opts--;
#endif
return set_option(str(LANG_RECORDING_SOURCE),
&global_settings.rec_source, INT, names,
sizeof(names)/sizeof(struct opt_items), NULL );
n_opts, NULL );
}
/* To be removed when we add support for sample rates and channel settings */
#if CONFIG_CODEC == SWCODEC
static bool recquality(void)
{
static const struct opt_items names[] = {
{ "MP3 64 kBit/s", TALK_ID( 64, UNIT_KBIT) },
{ "MP3 96 kBit/s", TALK_ID( 96, UNIT_KBIT) },
{ "MP3 128 kBit/s", TALK_ID( 128, UNIT_KBIT) },
{ "MP3 160 kBit/s", TALK_ID( 160, UNIT_KBIT) },
{ "MP3 192 kBit/s", TALK_ID( 192, UNIT_KBIT) },
{ "MP3 224 kBit/s", TALK_ID( 224, UNIT_KBIT) },
{ "MP3 320 kBit/s", TALK_ID( 320, UNIT_KBIT) },
{ "WV 900 kBit/s", TALK_ID( 900, UNIT_KBIT) },
{ "WAV 1411 kBit/s", TALK_ID(1411, UNIT_KBIT) }
};
return set_option(str(LANG_RECORDING_QUALITY),
&global_settings.rec_quality, INT,
names, sizeof (names)/sizeof(struct opt_items),
NULL );
}
#elif CONFIG_CODEC == MAS3587F
static bool recquality(void)
{
return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
&global_settings.rec_quality,
NULL, 1, 0, 7, NULL );
}
static bool receditable(void)
{
return set_bool(str(LANG_RECORDING_EDITABLE),
&global_settings.rec_editable);
}
#endif
#ifndef HAVE_UDA1380
static bool recfrequency(void)
{
@ -331,21 +386,6 @@ static bool recchannels(void)
}
#endif
#if CONFIG_CODEC == MAS3587F
static bool recquality(void)
{
return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
&global_settings.rec_quality,
NULL, 1, 0, 7, NULL );
}
static bool receditable(void)
{
return set_bool(str(LANG_RECORDING_EDITABLE),
&global_settings.rec_editable);
}
#endif
static bool rectimesplit(void)
{
static const struct opt_items names[] = {
@ -1011,13 +1051,13 @@ bool recording_menu(bool no_source)
struct menu_item items[13];
bool result;
#if CONFIG_CODEC == MAS3587F
#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
items[i].desc = ID2P(LANG_RECORDING_QUALITY);
items[i++].function = recquality;
#endif
#ifndef HAVE_UDA1380
/* We don't support frequency selection for UDA1380 yet. Let it just stay at
the default 44100 Hz. */
#ifndef HAVE_UDA1380
items[i].desc = ID2P(LANG_RECORDING_FREQUENCY);
items[i++].function = recfrequency;
#endif

View file

@ -103,10 +103,10 @@ int current_playmode(void)
#ifdef CONFIG_TUNER
audio_stat = get_radio_status();
if(audio_stat == FMRADIO_PLAYING)
if(audio_stat & FMRADIO_PLAYING)
return STATUS_RADIO;
if(audio_stat == FMRADIO_PAUSED)
if(audio_stat & FMRADIO_PAUSED)
return STATUS_RADIO_PAUSE;
#endif

View file

@ -554,6 +554,7 @@ int talk_buffer_steal(void)
}
#endif
reset_state();
return 0;
}
@ -728,6 +729,7 @@ int talk_value(long n, int unit, bool enqueue)
VOICE_PIXEL,
VOICE_PER_SEC,
VOICE_HERTZ,
VOICE_KBIT_PER_SEC,
};
#if CONFIG_CODEC != SWCODEC

View file

@ -41,6 +41,7 @@ enum {
UNIT_PER_SEC, /* per second */
UNIT_HERTZ, /* hertz */
UNIT_MB, /* Megabytes */
UNIT_KBIT, /* kilobits per sec */
UNIT_LAST /* END MARKER */
};

View file

@ -577,7 +577,7 @@ static bool dirbrowse(void)
if (global_settings.rec_startup) {
/* We fake being in the menu structure by calling
the appropriate parent when we drop out of each screen */
recording_screen();
recording_screen(false);
rec_menu();
main_menu();
}

View file

@ -38,7 +38,7 @@ bool charger_enabled;
static bool powered = false;
bool radio_powered()
bool radio_powered(void)
{
return powered;
}

View file

@ -31,6 +31,9 @@
#define AUDIO_STATUS_PRERECORD 8
#define AUDIO_STATUS_ERROR 16
#define AUDIO_STATUS_STAYON_FLAGS \
(AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE | AUDIO_STATUS_RECORD | AUDIO_)
#define AUDIOERR_DISK_FULL 1
#define AUDIO_GAIN_LINEIN 0
@ -69,6 +72,7 @@ void audio_resume(void);
void audio_next(void);
void audio_prev(void);
int audio_status(void);
bool audio_query_poweroff(void);
int audio_track_count(void); /* SWCODEC only */
void audio_pre_ff_rewind(void); /* SWCODEC only */
void audio_ff_rewind(long newtime);
@ -93,14 +97,56 @@ void audio_stop_recording(void);
void audio_pause_recording(void);
void audio_resume_recording(void);
void audio_new_file(const char *filename);
/* audio sources */
enum
{
AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */
AUDIO_SRC_MIC, /* monitor mic */
AUDIO_SRC_LINEIN, /* monitor line in */
#ifdef HAVE_SPDIF_IN
AUDIO_SRC_SPDIF, /* monitor spdif */
#endif
#if defined(HAVE_FMRADIO_IN) || defined(CONFIG_TUNER)
AUDIO_SRC_FMRADIO, /* monitor fm radio */
#endif
/* define new audio sources above this line */
AUDIO_SOURCE_LIST_END,
/* AUDIO_SRC_FMRADIO must be declared #ifdef CONFIG_TUNER but is not in
the list of recordable sources. HAVE_FMRADIO_IN implies CONFIG_TUNER. */
#if defined(HAVE_FMRADIO_IN) || !defined(CONFIG_TUNER)
AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END,
#else
AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END-1,
#endif
AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
};
/* channel modes */
enum
{
CHN_MODE_MONO = 1,
CHN_MODE_STEREO,
};
void audio_set_recording_options(int frequency, int quality,
int source, int channel_mode,
bool editable, int prerecord_time);
void audio_set_recording_gain(int left, int right, int type);
unsigned long audio_recorded_time(void);
unsigned long audio_num_recorded_bytes(void);
#if 0
#ifdef HAVE_SPDIF_POWER
void audio_set_spdif_power_setting(bool on);
#endif
#endif
unsigned long audio_get_spdif_sample_rate(void);
#if CONFIG_CODEC == SWCODEC
/* audio encoder functions (defined in playback.c) */
int audio_get_encoder_id(void);
void audio_load_encoder(int enc_id);
void audio_remove_encoder(void);
#endif /* CONFIG_CODEC == SWCODEC */

View file

@ -135,6 +135,9 @@
/* Someone with H100 and BDM, please verify if this works. */
/* #define HAVE_EEPROM */
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* !SIMULATOR */
/* Define this for S/PDIF input available */

View file

@ -132,6 +132,9 @@
/* Define this if the EEPROM chip is used */
#define HAVE_EEPROM_SETTINGS
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* !SIMULATOR */
/* Define this for S/PDIF input available */

View file

@ -140,4 +140,7 @@
/* Define this if there is an EEPROM chip */
#define HAVE_EEPROM
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
#endif /* SIMULATOR */

View file

@ -17,6 +17,7 @@
/* define this if you have access to the quickscreen */
#define HAVE_QUICKSCREEN
/* define this if you have access to the pitchscreen */
#define HAVE_PITCHSCREEN
@ -81,6 +82,9 @@
should be defined as well. */
#define HAVE_LCD_SLEEP
/* Define this for FM radio input available (not for SIMULATOR) */
#define HAVE_FMRADIO_IN
/* Define this if you have a Motorola SCF5250 */
#define CONFIG_CPU MCF5250

View file

@ -20,6 +20,22 @@
#ifndef FMRADIO_H
#define FMRADIO_H
/** declare some stuff here so powermgmt.c can properly tell if the radio is
actually playing and not just paused. This break in heirarchy is allowed
for audio_status(). **/
/* set when radio is playing or paused within fm radio screen */
#define FMRADIO_OFF 0x0
#define FMRADIO_PLAYING 0x1
#define FMRADIO_PAUSED 0x2
/* returns the IN flag */
#define FMRADIO_IN_SCREEN(s) ((s) & FMRADIO_IN_FLAG)
#define FMRADIO_STATUS_PLAYING(s) ((s) & FMRADIO_PLAYING_OUT)
#define FMRADIO_STATUS_PAUSED(s) ((s) & FMRADIO_PAUSED_OUT)
extern int get_radio_status(void);
extern int fmradio_read(int addr);
extern void fmradio_set(int addr, int data);

View file

@ -24,7 +24,6 @@
#include "file.h"
/* Audio file types. */
/* NOTE: When adding new audio types, also add to codec_labels[] in id3.c */
enum {
AFMT_UNKNOWN = 0, /* Unknown file format */
@ -46,9 +45,48 @@ enum {
/* New formats must be added to the end of this list */
AFMT_NUM_CODECS
AFMT_NUM_CODECS,
#if CONFIG_CODEC == SWCODEC
/* masks to decompose parts */
CODEC_AFMT_MASK = 0x0fff,
CODEC_TYPE_MASK = 0x7000,
/* switch for specifying codec type when requesting a filename */
CODEC_TYPE_DECODER = (0 << 12), /* default */
CODEC_TYPE_ENCODER = (1 << 12)
#endif
};
#if CONFIG_CODEC == SWCODEC
#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
{ label, codec_fname, codec_enc_fname, enc_ext }
#else
#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
{ label }
#endif
/* record describing the audio format */
struct afmt_entry
{
#if CONFIG_CODEC == SWCODEC
char label[8]; /* format label */
char *codec_fn; /* filename of decoder codec */
char *codec_enc_fn; /* filename of encoder codec */
char *ext; /* default extension for file (enc only for now) */
#else
char label[4];
#endif
};
/* database of labels and codecs. add formats per above enum */
extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS];
#if CONFIG_CODEC == SWCODEC
/* recording quality to AFMT_* */
extern const int rec_quality_info_afmt[9];
#endif
struct mp3entry {
char path[MAX_PATH];
char* title;

View file

@ -20,10 +20,22 @@
#ifndef PCM_RECORD_H
#define PCM_RECORD_H
void enc_set_parameters(int chunk_size, int num_chunks,
int samp_per_chunk, char *head_ptr, int head_size,
int enc_id);
void enc_get_inputs(int *buffer_size, int *channels, int *quality);
unsigned int* enc_alloc_chunk(void);
void enc_free_chunk(void);
int enc_wavbuf_near_empty(void);
char* enc_get_wav_data(int size);
extern void (*enc_set_header_callback)(void *head_buffer, int head_size,
int num_pcm_samples, bool is_file_header);
unsigned long pcm_rec_status(void);
void pcm_rec_init(void);
void pcm_rec_mux(int source);
int pcm_rec_current_bitrate(void);
int pcm_get_num_unprocessed(void);
void pcm_rec_get_peaks(int *left, int *right);
/* audio.h contains audio recording functions */

View file

@ -85,28 +85,59 @@ static const char* const genres[] = {
"Synthpop"
};
static const char* const codec_labels[] = {
"???", /* Unknown file format */
"MP1", /* MPEG Audio layer 1 */
"MP2", /* MPEG Audio layer 2 */
"MP3", /* MPEG Audio layer 3 */
/* database of audio formats */
const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
{
/* Unknown file format */
AFMT_ENTRY("???", NULL, NULL, NULL ),
/* MPEG Audio layer 1 */
AFMT_ENTRY("MP1", "mpa.codec", NULL, NULL ),
/* MPEG Audio layer 2 */
AFMT_ENTRY("MP2", "mpa.codec", NULL, NULL ),
/* MPEG Audio layer 3 */
AFMT_ENTRY("MP3", "mpa.codec", "mp3_enc.codec", ".mp3"),
#if CONFIG_CODEC == SWCODEC
"WAV", /* Uncompressed PCM in a WAV file */
"Ogg", /* Ogg Vorbis */
"FLAC", /* FLAC */
"MPC", /* Musepack */
"AC3", /* A/52 (aka AC3) audio */
"WV", /* WavPack */
"ALAC", /* Apple Lossless Audio Codec */
"AAC", /* Advanced Audio Coding in M4A container */
"SHN", /* Shorten */
"AIFF", /* Audio Interchange File Format */
"SID", /* SID File Format */
/* Uncompressed PCM in a WAV file */
AFMT_ENTRY("WAV", "wav.codec", "wav_enc.codec", ".wav"),
/* Ogg Vorbis */
AFMT_ENTRY("Ogg", "vorbis.codec", NULL, NULL ),
/* FLAC */
AFMT_ENTRY("FLAC", "flac.codec", NULL, NULL ),
/* Musepack */
AFMT_ENTRY("MPC", "mpc.codec", NULL, NULL ),
/* A/52 (aka AC3) audio */
AFMT_ENTRY("AC3", "a52.codec", NULL, NULL ),
/* WavPack */
AFMT_ENTRY("WV", "wavpack.codec", "wavpack_enc.codec", ".wv" ),
/* Apple Lossless Audio Codec */
AFMT_ENTRY("ALAC", "alac.codec", NULL, NULL ),
/* Advanced Audio Coding in M4A container */
AFMT_ENTRY("AAC", "aac.codec", NULL, NULL ),
/* Shorten */
AFMT_ENTRY("SHN", "shorten.codec", NULL, NULL ),
/* Audio Interchange File Format */
AFMT_ENTRY("AIFF", "aiff.codec", NULL, NULL ),
/* SID File Format */
AFMT_ENTRY("SID", "sid.codec", NULL, NULL ),
#endif
};
#if CONFIG_CODEC == SWCODEC
/* recording quality to AFMT_* */
const int rec_quality_info_afmt[9] =
{
AFMT_MPA_L3, /* MPEG L3 64 kBit/s */
AFMT_MPA_L3, /* MPEG L3 96 kBit/s */
AFMT_MPA_L3, /* MPEG L3 128 kBit/s */
AFMT_MPA_L3, /* MPEG L3 160 kBit/s */
AFMT_MPA_L3, /* MPEG L3 192 kBit/s */
AFMT_MPA_L3, /* MPEG L3 224 kBit/s */
AFMT_MPA_L3, /* MPEG L3 320 kBit/s */
AFMT_WAVPACK, /* WavPack 909 kBit/s */
AFMT_PCM_WAV, /* PCM Wav 1411 kBit/s */
};
#endif /* SWCODEC */
char* id3_get_genre(const struct mp3entry* id3)
{
if( id3->genre_string )
@ -119,8 +150,8 @@ char* id3_get_genre(const struct mp3entry* id3)
char* id3_get_codec(const struct mp3entry* id3)
{
if (id3->codectype < sizeof(codec_labels)/sizeof(char*)) {
return (char*)codec_labels[id3->codectype];
if (id3->codectype < AFMT_NUM_CODECS) {
return (char*)audio_formats[id3->codectype].label;
} else {
return NULL;
}

View file

@ -2484,7 +2484,7 @@ void audio_set_recording_options(int frequency, int quality,
DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
if(source == 0) /* Mic */
if(source == AUDIO_SRC_MIC)
{
/* Copy left channel to right (mono mode) */
mas_codec_writereg(8, 0x8000);

File diff suppressed because it is too large Load diff

View file

@ -424,6 +424,7 @@ static void battery_status_update(void)
* 1) The USB is connected
* 2) The charger is connected
* 3) We are recording, or recording with pause
* 4) The radio is playing
*/
static void handle_auto_poweroff(void)
{
@ -442,7 +443,7 @@ static void handle_auto_poweroff(void)
if(timeout &&
#ifdef CONFIG_TUNER
(!radio_powered()) &&
(!(get_radio_status() & FMRADIO_PLAYING)) &&
#endif
!usb_inserted() &&
((audio_stat == 0) ||