Big Patch adds primarily: Samplerate and format selection to recording for SWCODEC. Supprort for samplerates changing in playback (just goes with the recording part inseparably). Samplerates to all encoders. Encoders can be configured individually on a menu specific to the encoder in the recording menu. File creation is delayed until flush time to reduce spinups when splitting. Misc: statusbar icons for numbers are individual digits to display any number. Audio buffer was rearranged to maximize memory available to recording and properly reinitialized when trashed. ColdFire PCM stuff moved to target tree to avoid a complicated mess when adding samplerate switching. Some needed API changes and to neaten up growing gap between hardware and software codecs.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11452 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2006-11-06 18:07:30 +00:00
parent 0b22795e26
commit 0f5cb94aa4
58 changed files with 4769 additions and 2781 deletions

View file

@ -20,6 +20,20 @@
#define AUDIO_H
#include <stdbool.h>
#include <sys/types.h>
/* These must always be included with audio.h for this to compile under
cetain conditions. Do it here or else spread the complication around to
many files. */
#if CONFIG_CODEC == SWCODEC
#include "pcm_sampr.h"
#include "pcm_playback.h"
#ifdef HAVE_RECORDING
#include "pcm_record.h"
#include "id3.h"
#include "enc_base.h"
#endif /* HAVE_RECORDING */
#endif /* CONFIG_CODEC == SWCODEC */
#ifdef SIMULATOR
#define audio_play(x) sim_audio_play(x)
@ -31,9 +45,6 @@
#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
@ -72,10 +83,11 @@ void audio_resume(void);
void audio_next(void);
void audio_prev(void);
int audio_status(void);
bool audio_query_poweroff(void);
#if CONFIG_CODEC == SWCODEC
int audio_track_count(void); /* SWCODEC only */
long audio_filebufused(void); /* SWCODEC only */
void audio_pre_ff_rewind(void); /* SWCODEC only */
#endif /* CONFIG_CODEC == SWCODEC */
void audio_ff_rewind(long newtime);
void audio_flush_and_reload_tracks(void);
struct mp3entry* audio_current_track(void);
@ -89,18 +101,28 @@ void audio_error_clear(void);
int audio_get_file_pos(void);
void audio_beep(int duration);
void audio_init_playback(void);
unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
/* audio recording functions */
void audio_init_recording(unsigned int buffer_offset);
void audio_close_recording(void);
void audio_record(const char *filename);
void audio_stop_recording(void);
void audio_pause_recording(void);
void audio_resume_recording(void);
void audio_new_file(const char *filename);
/* channel modes */
enum rec_channel_modes
{
__CHN_MODE_START_INDEX = -1,
CHN_MODE_STEREO,
CHN_MODE_MONO,
CHN_NUM_MODES
};
#if CONFIG_CODEC == SWCODEC
/* channel mode capability bits */
#define CHN_CAP_STEREO (1 << CHN_MODE_STEREO)
#define CHN_CAP_MONO (1 << CHN_MODE_MONO)
#define CHN_CAP_ALL (CHN_CAP_STEREO | CHN_CAP_MONO)
#endif /* CONFIG_CODEC == SWCODEC */
/* audio sources */
enum
enum audio_sources
{
AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */
AUDIO_SRC_MIC, /* monitor mic */
@ -123,33 +145,57 @@ enum
AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
};
/* channel modes */
enum
#ifdef HAVE_RECORDING
/* parameters for audio_set_recording_options */
struct audio_recording_options
{
CHN_MODE_MONO = 1,
CHN_MODE_STEREO,
int rec_source;
int rec_frequency;
int rec_channels;
int rec_prerecord_time;
#if CONFIG_CODEC == SWCODEC
int rec_source_flags; /* for rec_set_source */
struct encoder_config enc_config;
#else
int rec_quality;
bool rec_editable;
#endif
};
void audio_set_recording_options(int frequency, int quality,
int source, int channel_mode,
bool editable, int prerecord_time);
/* audio recording functions */
void audio_init_recording(unsigned int buffer_offset);
void audio_close_recording(void);
void audio_record(const char *filename);
void audio_stop_recording(void);
void audio_pause_recording(void);
void audio_resume_recording(void);
void audio_new_file(const char *filename);
void audio_set_recording_options(struct audio_recording_options *options);
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
#if CONFIG_CODEC == SWCODEC
/* SWCODEC recoring functions */
/* playback.c */
bool audio_load_encoder(int afmt);
void audio_remove_encoder(void);
unsigned char *audio_get_recording_buffer(size_t *buffer_size);
#endif /* CONFIG_CODEC == SWCODEC */
#endif /* HAVE_RECORDING */
#ifdef HAVE_SPDIF_IN
#ifdef HAVE_SPDIF_POWER
void audio_set_spdif_power_setting(bool on);
bool audio_get_spdif_power_setting(void);
#endif
#endif
unsigned long audio_get_spdif_sample_rate(void);
/* returns index into rec_master_sampr_list */
int audio_get_spdif_sample_rate(void);
/* > 0: monitor EBUin, 0: Monitor IISrecv, <0: reset only */
void audio_spdif_set_monitor(int monitor_spdif);
#endif /* HAVE_SPDIF_IN */
unsigned long audio_prev_elapsed(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

@ -84,6 +84,12 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING 1
/* define hardware samples rate caps mask */
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define the bitmask of recording sample rates */
#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
#define HAVE_AGC
#ifndef SIMULATOR

View file

@ -77,6 +77,12 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING 1
/* define hardware samples rate caps mask */
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define the bitmask of recording sample rates */
#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
#define HAVE_AGC
#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */

View file

@ -72,6 +72,12 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING 1
/* define hardware samples rate caps mask */
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define the bitmask of recording sample rates */
#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
#define HAVE_AGC
#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
@ -157,4 +163,3 @@
/* Define this for FM radio input available */
#define HAVE_FMRADIO_IN

View file

@ -9,6 +9,12 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING 1
/* define the bitmask of hardware sample rates */
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define the bitmask of recording sample rates */
#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
/* define this if you have a bitmap LCD display */
#define HAVE_LCD_BITMAP 1

View file

@ -24,13 +24,19 @@
#include "file.h"
/* Audio file types. */
enum {
enum
{
AFMT_UNKNOWN = 0, /* Unknown file format */
/* start formats */
AFMT_MPA_L1, /* MPEG Audio layer 1 */
AFMT_MPA_L2, /* MPEG Audio layer 2 */
AFMT_MPA_L3, /* MPEG Audio layer 3 */
AFMT_AIFF, /* Audio Interchange File Format */
#if CONFIG_CODEC == SWCODEC
AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */
AFMT_OGG_VORBIS, /* Ogg Vorbis */
AFMT_FLAC, /* FLAC */
@ -40,54 +46,91 @@ enum {
AFMT_ALAC, /* Apple Lossless Audio Codec */
AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */
AFMT_SHN, /* Shorten */
AFMT_AIFF, /* Audio Interchange File Format */
AFMT_SID, /* SID File Format */
AFMT_ADX, /* ADX */
AFMT_ADX, /* ADX File Format */
#endif
/* New formats must be added to the end of this list */
/* add new formats at any index above this line to have a sensible order -
specified array index inits are used */
/* format arrays defined in id3.c */
AFMT_NUM_CODECS,
#if CONFIG_CODEC == SWCODEC
#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
/* 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
CODEC_TYPE_ENCODER = (1 << 12),
#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
};
#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
#define CODEC_EXTENSION "codec"
#ifdef HAVE_RECORDING
#define ENCODER_SUFFIX "_enc"
enum rec_format_indexes
{
__REC_FORMAT_START_INDEX = -1,
/* start formats */
REC_FORMAT_PCM_WAV,
REC_FORMAT_WAVPACK,
REC_FORMAT_MPA_L3,
/* add new formats at any index above this line to have a sensible order -
specified array index inits are used
REC_FORMAT_CFG_NUM_BITS should allocate enough bits to hold the range
REC_FORMAT_CFG_VALUE_LIST should be in same order as indexes
*/
REC_NUM_FORMATS,
REC_FORMAT_DEFAULT = REC_FORMAT_PCM_WAV,
REC_FORMAT_CFG_NUM_BITS = 2
};
#define REC_FORMAT_CFG_VAL_LIST "wave,wvpk,mpa3"
/* get REC_FORMAT_* corresponding AFMT_* */
extern const int rec_format_afmt[REC_NUM_FORMATS];
/* get AFMT_* corresponding REC_FORMAT_* */
extern const int afmt_rec_format[AFMT_NUM_CODECS];
#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
{ label, root_fname, enc_root_fname, ext_list }
#else /* !HAVE_RECORDING */
#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
{ label, root_fname, ext_list }
#endif /* HAVE_RECORDING */
#else /* !SWCODEC */
#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
{ label, ext_list }
#endif /* CONFIG_CODEC == SWCODEC */
/* 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];
#if CONFIG_CODEC == SWCODEC
char *codec_root_fn; /* root codec filename (sans _enc and .codec) */
#ifdef HAVE_RECORDING
char *codec_enc_root_fn; /* filename of encoder codec */
#endif
#endif
char *ext_list; /* double NULL terminated extension
list for type with the first as
the default for recording */
};
/* 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

@ -19,11 +19,23 @@
#ifndef PCM_PLAYBACK_H
#define PCM_PLAYBACK_H
#include <sys/types.h>
/* Typedef for registered callback (play and record) */
typedef void (*pcm_more_callback_type)(unsigned char **start,
size_t *size);
void pcm_init(void);
/* set the pcm frequency - use values in hw_sampr_list
* use -1 for the default frequency
*/
void pcm_set_frequency(unsigned int frequency);
/* apply settings to hardware immediately */
void pcm_apply_settings(bool reset);
/* This is for playing "raw" PCM data */
void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
void pcm_play_data(pcm_more_callback_type get_more,
unsigned char* start, size_t size);
void pcm_calculate_peaks(int *left, int *right);
@ -35,4 +47,4 @@ void pcm_play_pause(bool play);
bool pcm_is_paused(void);
bool pcm_is_playing(void);
#endif
#endif /* PCM_PLAYBACK_H */

View file

@ -20,24 +20,44 @@
#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);
#define DMA_REC_ERROR_DMA ((size_t)-1)
#ifdef HAVE_SPDIF_IN
#define DMA_REC_ERROR_SPDIF ((size_t)-2)
#endif
/* Use AUDIO_SRC_* enumeration values */
void pcm_set_monitor(int monitor);
void pcm_set_rec_source(int source);
/**
* RAW pcm data recording
* These calls are nescessary only when using the raw pcm apis directly.
*/
/* Initialize pcm recording interface */
void pcm_init_recording(void);
/* Uninitialze pcm recording interface */
void pcm_close_recording(void);
/* Start recording "raw" PCM data */
void pcm_record_data(pcm_more_callback_type more_ready,
unsigned char *start, size_t size);
/* Stop tranferring data into supplied buffer */
void pcm_stop_recording(void);
void pcm_calculate_rec_peaks(int *left, int *right);
/** General functions for high level codec recording **/
void pcm_rec_error_clear(void);
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_rec_encoder_afmt(void); /* AFMT_* value, AFMT_UNKNOWN if none */
int pcm_rec_rec_format(void); /* Format index or -1 otherwise */
unsigned long pcm_rec_sample_rate(void);
int pcm_get_num_unprocessed(void);
void pcm_rec_get_peaks(int *left, int *right);
/* audio.h contains audio recording functions */
/* audio.h contains audio_* recording functions */
#endif
#endif /* PCM_RECORD_H */

View file

@ -21,7 +21,6 @@
#define __SYSTEM_H__
#include "cpu.h"
#include "config.h"
#include "stdbool.h"
extern void system_reboot (void);
@ -111,6 +110,23 @@ const char *get_cpu_boost_tracker(void);
#define MAX(a, b) (((a)>(b))?(a):(b))
#endif
/* return number of elements in array a */
#define ARRAYLEN(a) (sizeof(a)/sizeof((a)[0]))
/* return p incremented by specified number of bytes */
#define SKIPBYTES(p, count) ((typeof (p))((char *)(p) + (count)))
#define P2_M1(p2) ((1 << (p2))-1)
/* align up or down to nearest 2^p2 */
#define ALIGN_DOWN_P2(n, p2) ((n) & ~P2_M1(p2))
#define ALIGN_UP_P2(n, p2) ALIGN_DOWN_P2((n) + P2_M1(p2),p2)
/* align up or down to nearest integer multiple of a */
#define ALIGN_DOWN(n, a) ((n)/(a)*(a))
#define ALIGN_UP(n, a) ALIGN_DOWN((n)+((a)-1),a)
/* live endianness conversion */
#ifdef ROCKBOX_LITTLE_ENDIAN
#define letoh16(x) (x)
#define letoh32(x) (x)
@ -120,6 +136,8 @@ const char *get_cpu_boost_tracker(void);
#define betoh32(x) swap32(x)
#define htobe16(x) swap16(x)
#define htobe32(x) swap32(x)
#define swap_odd_even_be32(x) (x)
#define swap_odd_even_le32(x) swap_odd_even32(x)
#else
#define letoh16(x) swap16(x)
#define letoh32(x) swap32(x)
@ -129,6 +147,37 @@ const char *get_cpu_boost_tracker(void);
#define betoh32(x) (x)
#define htobe16(x) (x)
#define htobe32(x) (x)
#define swap_odd_even_be32(x) swap_odd_even32(x)
#define swap_odd_even_le32(x) (x)
#endif
/* static endianness conversion */
#define SWAP_16(x) ((typeof(x))(unsigned short)(((unsigned short)(x) >> 8) | \
((unsigned short)(x) << 8)))
#define SWAP_32(x) ((typeof(x))(unsigned long)( ((unsigned long)(x) >> 24) | \
(((unsigned long)(x) & 0xff0000ul) >> 8) | \
(((unsigned long)(x) & 0xff00ul) << 8) | \
((unsigned long)(x) << 24)))
#ifdef ROCKBOX_LITTLE_ENDIAN
#define LE_TO_H16(x) (x)
#define LE_TO_H32(x) (x)
#define H_TO_LE16(x) (x)
#define H_TO_LE32(x) (x)
#define BE_TO_H16(x) SWAP_16(x)
#define BE_TO_H32(x) SWAP_32(x)
#define H_TO_BE16(x) SWAP_16(x)
#define H_TO_BE32(x) SWAP_32(x)
#else
#define LE_TO_H16(x) SWAP_16(x)
#define LE_TO_H32(x) SWAP_32(x)
#define H_TO_LE16(x) SWAP_16(x)
#define H_TO_LE32(x) SWAP_32(x)
#define BE_TO_H16(x) (x)
#define BE_TO_H32(x) (x)
#define H_TO_BE16(x) (x)
#define H_TO_BE32(x) (x)
#endif
@ -181,6 +230,7 @@ enum {
: /* %0 */ I_CONSTRAINT((char)(mask)), \
/* %1 */ "z"(address-GBR))
#endif /* CONFIG_CPU == SH7034 */
#ifndef SIMULATOR
@ -388,7 +438,20 @@ static inline unsigned long swap32(unsigned long value)
#define invalidate_icache()
#endif
#else
#ifndef CPU_COLDFIRE
static inline unsigned long swap_odd_even32(unsigned long value)
{
/*
result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
*/
unsigned long t = value & 0xff00ff00;
return (t >> 8) | ((t ^ value) << 8);
}
#endif
#else /* SIMULATOR */
static inline unsigned short swap16(unsigned short value)
/*
@ -412,8 +475,18 @@ static inline unsigned long swap32(unsigned long value)
return (lo << 16) | hi;
}
static inline unsigned long swap_odd_even32(unsigned long value)
{
/*
result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
*/
unsigned long t = value & 0xff00ff00;
return (t >> 8) | ((t ^ value) << 8);
}
#define invalidate_icache()
#endif
#endif /* !SIMULATOR */
#endif
#endif /* __SYSTEM_H__ */

View file

@ -142,7 +142,10 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list);
void sleep_thread(int ticks);
void block_thread(struct thread_entry **thread, int timeout);
void wakeup_thread(struct thread_entry **thread);
#ifdef HAVE_PRIORITY_SCHEDULING
int thread_set_priority(struct thread_entry *thread, int priority);
int thread_get_priority(struct thread_entry *thread);
#endif
void init_threads(void);
int thread_stack_usage(const struct thread_entry *thread);
int thread_get_status(const struct thread_entry *thread);

View file

@ -24,6 +24,16 @@
extern void tlv320_init(void);
extern void tlv320_reset(void);
/**
* Sets internal sample rate for DAC and ADC relative to MCLK
* Selection for frequency:
* Fs: tlv: with:
* 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
* 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
* 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
* 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
*/
extern void tlv320_set_frequency(unsigned fsel);
extern void tlv320_enable_output(bool enable);
extern void tlv320_set_headphone_vol(int vol_l, int vol_r);
extern void tlv320_set_recvol(int left, int right, int type);

View file

@ -28,8 +28,17 @@ extern void uda1380_set_bass(int value);
extern void uda1380_set_treble(int value);
extern int uda1380_mute(int mute);
extern void uda1380_close(void);
extern void uda1380_set_nsorder(int order);
/**
* Sets frequency settings for DAC and ADC relative to MCLK
*
* Selection for frequency ranges:
* Fs: range: with:
* 11025: 0 = 6.25 to 12.5 SCLK, LRCK: Audio Clk / 16
* 22050: 1 = 12.5 to 25 SCLK, LRCK: Audio Clk / 8
* 44100: 2 = 25 to 50 SCLK, LRCK: Audio Clk / 4 (default)
* 88200: 3 = 50 to 100 SCLK, LRCK: Audio Clk / 2
*/
extern void uda1380_set_frequency(unsigned fsel);
extern void uda1380_enable_recording(bool source_mic);
extern void uda1380_disable_recording(void);
extern void uda1380_set_recvol(int left, int right, int type);