forked from len0rd/rockbox
FS#5992 Reworked playback.c to fix voice bugs by Steve Bavin. Fixed to
work with the new scheduler and handled properly and fast the track skipping. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10966 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
4553069f9d
commit
815684aced
2 changed files with 173 additions and 109 deletions
|
|
@ -232,7 +232,7 @@ static inline void pcmbuf_add_chunk(void)
|
||||||
pcmbuf_current->link = NULL;
|
pcmbuf_current->link = NULL;
|
||||||
/* This is single use only */
|
/* This is single use only */
|
||||||
pcmbuf_event_handler = NULL;
|
pcmbuf_event_handler = NULL;
|
||||||
if (pcmbuf_read) {
|
if (pcmbuf_read != NULL) {
|
||||||
if (pcmbuf_flush)
|
if (pcmbuf_flush)
|
||||||
{
|
{
|
||||||
pcmbuf_write_end->link = pcmbuf_read->link;
|
pcmbuf_write_end->link = pcmbuf_read->link;
|
||||||
|
|
@ -305,14 +305,14 @@ bool pcmbuf_is_lowdata(void)
|
||||||
/* Amount of bytes left in the buffer. */
|
/* Amount of bytes left in the buffer. */
|
||||||
inline size_t pcmbuf_free(void)
|
inline size_t pcmbuf_free(void)
|
||||||
{
|
{
|
||||||
if (pcmbuf_read)
|
if (pcmbuf_read != NULL)
|
||||||
{
|
{
|
||||||
size_t read = (size_t)pcmbuf_read->addr;
|
void *read = pcmbuf_read->addr;
|
||||||
size_t write =
|
void *write = &audiobuffer[audiobuffer_pos + audiobuffer_fillpos];
|
||||||
(size_t)&audiobuffer[audiobuffer_pos + audiobuffer_fillpos];
|
|
||||||
if (read < write)
|
if (read < write)
|
||||||
read += pcmbuf_size;
|
return (size_t)(read - write) + pcmbuf_size;
|
||||||
return read - write;
|
else
|
||||||
|
return (size_t) (read - write);
|
||||||
}
|
}
|
||||||
return pcmbuf_size;
|
return pcmbuf_size;
|
||||||
}
|
}
|
||||||
|
|
@ -335,7 +335,6 @@ bool pcmbuf_crossfade_init(bool manual_skip)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logf("pcmbuf_crossfade_init");
|
|
||||||
pcmbuf_boost(true);
|
pcmbuf_boost(true);
|
||||||
|
|
||||||
/* Don't enable mix mode when skipping tracks manually. */
|
/* Don't enable mix mode when skipping tracks manually. */
|
||||||
|
|
@ -444,10 +443,13 @@ void pcmbuf_play_start(void)
|
||||||
* until dma has been initialized. */
|
* until dma has been initialized. */
|
||||||
pcm_mute(true);
|
pcm_mute(true);
|
||||||
|
|
||||||
|
if (pcmbuf_read != NULL)
|
||||||
|
{
|
||||||
last_chunksize = pcmbuf_read->size;
|
last_chunksize = pcmbuf_read->size;
|
||||||
pcmbuf_unplayed_bytes -= last_chunksize;
|
pcmbuf_unplayed_bytes -= last_chunksize;
|
||||||
pcm_play_data(pcmbuf_callback,
|
pcm_play_data(pcmbuf_callback,
|
||||||
(unsigned char *)pcmbuf_read->addr, last_chunksize);
|
(unsigned char *)pcmbuf_read->addr, last_chunksize);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now unmute the audio. */
|
/* Now unmute the audio. */
|
||||||
pcm_mute(false);
|
pcm_mute(false);
|
||||||
|
|
@ -462,7 +464,6 @@ static bool pcmbuf_flush_fillpos(void)
|
||||||
if (audiobuffer_fillpos) {
|
if (audiobuffer_fillpos) {
|
||||||
/* Never use the last buffer descriptor */
|
/* Never use the last buffer descriptor */
|
||||||
while (pcmbuf_write == pcmbuf_write_end) {
|
while (pcmbuf_write == pcmbuf_write_end) {
|
||||||
logf("pcmbuf_flush_fillpos no descriptors");
|
|
||||||
/* Deboost to let the playback catchup */
|
/* Deboost to let the playback catchup */
|
||||||
pcmbuf_boost(false);
|
pcmbuf_boost(false);
|
||||||
/* If this happens, something is being stupid */
|
/* If this happens, something is being stupid */
|
||||||
|
|
@ -511,7 +512,7 @@ static void crossfade_process_buffer(size_t fade_in_delay,
|
||||||
fade_out_rem -= block_rem;
|
fade_out_rem -= block_rem;
|
||||||
|
|
||||||
/* Fade this block */
|
/* Fade this block */
|
||||||
while (block_rem > 0)
|
while (block_rem > 0 && fade_out_chunk != NULL)
|
||||||
{
|
{
|
||||||
/* Fade one sample */
|
/* Fade one sample */
|
||||||
short *buf = (short *)(fade_out_chunk->addr);
|
short *buf = (short *)(fade_out_chunk->addr);
|
||||||
|
|
@ -777,7 +778,8 @@ static bool prepare_insert(size_t length)
|
||||||
logf("pcm starting");
|
logf("pcm starting");
|
||||||
pcmbuf_play_start();
|
pcmbuf_play_start();
|
||||||
}
|
}
|
||||||
} else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark)
|
}
|
||||||
|
else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark)
|
||||||
pcmbuf_under_watermark();
|
pcmbuf_under_watermark();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -823,7 +825,12 @@ void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix)
|
||||||
{
|
{
|
||||||
if (mix)
|
if (mix)
|
||||||
{
|
{
|
||||||
if (pcmbuf_mix_chunk || pcmbuf_read->link)
|
if (pcmbuf_read == NULL)
|
||||||
|
{
|
||||||
|
*realsize = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (pcmbuf_mix_chunk || pcmbuf_read->link)
|
||||||
{
|
{
|
||||||
*realsize = MIN(length, PCMBUF_MIX_CHUNK);
|
*realsize = MIN(length, PCMBUF_MIX_CHUNK);
|
||||||
return voicebuf;
|
return voicebuf;
|
||||||
|
|
@ -888,7 +895,7 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
|
||||||
short *pcmbuf_end = (short *)fadebuf;
|
short *pcmbuf_end = (short *)fadebuf;
|
||||||
size_t samples = NATIVE_FREQUENCY / 1000 * duration;
|
size_t samples = NATIVE_FREQUENCY / 1000 * duration;
|
||||||
|
|
||||||
if (pcm_is_playing())
|
if (pcm_is_playing() && pcmbuf_read != NULL)
|
||||||
{
|
{
|
||||||
if (pcmbuf_read->link)
|
if (pcmbuf_read->link)
|
||||||
{
|
{
|
||||||
|
|
@ -971,7 +978,7 @@ void pcmbuf_mix_voice(size_t length)
|
||||||
short *obuf;
|
short *obuf;
|
||||||
size_t chunk_samples;
|
size_t chunk_samples;
|
||||||
|
|
||||||
if (!pcmbuf_mix_chunk && pcmbuf_read)
|
if (pcmbuf_mix_chunk == NULL && pcmbuf_read != NULL)
|
||||||
{
|
{
|
||||||
pcmbuf_mix_chunk = pcmbuf_read->link;
|
pcmbuf_mix_chunk = pcmbuf_read->link;
|
||||||
/* Start 1/8s into the next chunk */
|
/* Start 1/8s into the next chunk */
|
||||||
|
|
|
||||||
223
apps/playback.c
223
apps/playback.c
|
|
@ -22,6 +22,8 @@
|
||||||
/* TODO: Also play, stop ^^ */
|
/* TODO: Also play, stop ^^ */
|
||||||
/* TODO: Can use the track changed callback to detect end of track and seek
|
/* TODO: Can use the track changed callback to detect end of track and seek
|
||||||
* in the previous track until this happens */
|
* in the previous track until this happens */
|
||||||
|
/* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
|
||||||
|
* play whilst audio is paused */
|
||||||
/* Design: we have prev_ti already, have a conditional for what type of seek
|
/* Design: we have prev_ti already, have a conditional for what type of seek
|
||||||
* to do on a seek request, if it is a previous track seek, skip previous,
|
* to do on a seek request, if it is a previous track seek, skip previous,
|
||||||
* and in the request_next_track callback set the offset up the same way that
|
* and in the request_next_track callback set the offset up the same way that
|
||||||
|
|
@ -39,7 +41,6 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "backlight.h"
|
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
|
@ -81,10 +82,7 @@
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static volatile bool audio_codec_loaded;
|
#define PLAYBACK_VOICE
|
||||||
static volatile bool voice_codec_loaded;
|
|
||||||
static volatile bool playing;
|
|
||||||
static volatile bool paused;
|
|
||||||
|
|
||||||
|
|
||||||
/* default point to start buffer refill */
|
/* default point to start buffer refill */
|
||||||
|
|
@ -99,10 +97,10 @@ static volatile bool paused;
|
||||||
|
|
||||||
/* macros to enable logf for queues */
|
/* macros to enable logf for queues */
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
#define LOGF_QUEUES /* Define this for logf output of all queuing */
|
#define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOGF_QUEUES
|
#ifdef PLAYBACK_LOGQUEUES
|
||||||
#define LOGFQUEUE(s) logf("%s", s)
|
#define LOGFQUEUE(s) logf("%s", s)
|
||||||
#else
|
#else
|
||||||
#define LOGFQUEUE(s)
|
#define LOGFQUEUE(s)
|
||||||
|
|
@ -159,6 +157,14 @@ enum {
|
||||||
#endif
|
#endif
|
||||||
#define CODEC_IRAM_SIZE 0xc000
|
#define CODEC_IRAM_SIZE 0xc000
|
||||||
|
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
|
#ifdef SIMULATOR
|
||||||
|
static unsigned char sim_iram[CODEC_IRAM_SIZE];
|
||||||
|
#undef CODEC_IRAM_ORIGIN
|
||||||
|
#define CODEC_IRAM_ORIGIN sim_iram
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
extern bool audio_is_initialized;
|
extern bool audio_is_initialized;
|
||||||
#else
|
#else
|
||||||
|
|
@ -170,13 +176,9 @@ static bool audio_is_initialized = false;
|
||||||
static struct mutex mutex_codecthread;
|
static struct mutex mutex_codecthread;
|
||||||
static struct event_queue codec_callback_queue;
|
static struct event_queue codec_callback_queue;
|
||||||
|
|
||||||
static struct mp3entry id3_voice;
|
static volatile bool audio_codec_loaded;
|
||||||
|
static volatile bool playing;
|
||||||
static char *voicebuf;
|
static volatile bool paused;
|
||||||
static size_t voice_remaining;
|
|
||||||
static bool voice_is_playing;
|
|
||||||
static void (*voice_getmore)(unsigned char** start, int* size);
|
|
||||||
static struct thread_entry *voice_thread_p = NULL;
|
|
||||||
|
|
||||||
/* Is file buffer currently being refilled? */
|
/* Is file buffer currently being refilled? */
|
||||||
static volatile bool filling IDATA_ATTR;
|
static volatile bool filling IDATA_ATTR;
|
||||||
|
|
@ -197,9 +199,7 @@ size_t filebufused;
|
||||||
static volatile size_t buf_ridx IDATA_ATTR;
|
static volatile size_t buf_ridx IDATA_ATTR;
|
||||||
static volatile size_t buf_widx IDATA_ATTR;
|
static volatile size_t buf_widx IDATA_ATTR;
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
|
||||||
static unsigned char *iram_buf[2];
|
static unsigned char *iram_buf[2];
|
||||||
#endif
|
|
||||||
static unsigned char *dram_buf[2];
|
static unsigned char *dram_buf[2];
|
||||||
|
|
||||||
/* Step count to the next unbuffered track. */
|
/* Step count to the next unbuffered track. */
|
||||||
|
|
@ -209,7 +209,7 @@ static int last_peek_offset;
|
||||||
track ring structure. */
|
track ring structure. */
|
||||||
static int track_ridx;
|
static int track_ridx;
|
||||||
static int track_widx;
|
static int track_widx;
|
||||||
static bool track_changed;
|
static bool track_changed; /* Audio and codec threads */
|
||||||
|
|
||||||
/* Partially loaded song's file handle to continue buffering later. */
|
/* Partially loaded song's file handle to continue buffering later. */
|
||||||
static int current_fd;
|
static int current_fd;
|
||||||
|
|
@ -218,23 +218,20 @@ static int current_fd;
|
||||||
static size_t fill_bytesleft;
|
static size_t fill_bytesleft;
|
||||||
|
|
||||||
/* Track info structure about songs in the file buffer. */
|
/* Track info structure about songs in the file buffer. */
|
||||||
static struct track_info tracks[MAX_TRACK];
|
static struct track_info tracks[MAX_TRACK]; /* Audio thread */
|
||||||
|
|
||||||
/* Pointer to track info structure about current song playing. */
|
/* Pointer to track info structure about current song playing. */
|
||||||
static struct track_info *cur_ti;
|
static struct track_info *cur_ti; /* Audio and codec threads */
|
||||||
static struct track_info *prev_ti;
|
static struct track_info *prev_ti; /* Audio and codec threads */
|
||||||
|
|
||||||
/* Have we reached end of the current playlist. */
|
/* Have we reached end of the current playlist. */
|
||||||
static bool playlist_end = false;
|
static bool playlist_end = false; /* Audio thread */
|
||||||
|
|
||||||
/* Codec API including function callbacks. */
|
|
||||||
extern struct codec_api ci;
|
|
||||||
extern struct codec_api ci_voice;
|
|
||||||
|
|
||||||
/* Was the skip being executed manual or automatic? */
|
/* Was the skip being executed manual or automatic? */
|
||||||
static bool automatic_skip;
|
static bool automatic_skip = false; /* Audio and codec threads */
|
||||||
static bool dir_skip = false;
|
static bool dir_skip = false; /* Audio thread */
|
||||||
static bool new_playlist = false;
|
static bool new_playlist = false; /* Audio thread */
|
||||||
|
static int wps_offset = 0;
|
||||||
|
|
||||||
/* Callback function to call when current track has really changed. */
|
/* Callback function to call when current track has really changed. */
|
||||||
void (*track_changed_callback)(struct mp3entry *id3);
|
void (*track_changed_callback)(struct mp3entry *id3);
|
||||||
|
|
@ -250,6 +247,7 @@ static bool v1first = false;
|
||||||
|
|
||||||
/* Multiple threads */
|
/* Multiple threads */
|
||||||
static const char * get_codec_filename(int enc_spec);
|
static const char * get_codec_filename(int enc_spec);
|
||||||
|
static void set_filebuf_watermark(int seconds);
|
||||||
|
|
||||||
/* Audio thread */
|
/* Audio thread */
|
||||||
static struct event_queue audio_queue;
|
static struct event_queue audio_queue;
|
||||||
|
|
@ -257,12 +255,12 @@ static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
|
||||||
static const char audio_thread_name[] = "audio";
|
static const char audio_thread_name[] = "audio";
|
||||||
|
|
||||||
static void audio_thread(void);
|
static void audio_thread(void);
|
||||||
static void set_filebuf_watermark(int seconds);
|
|
||||||
static void audio_initiate_track_change(long direction);
|
static void audio_initiate_track_change(long direction);
|
||||||
static bool audio_have_tracks(void);
|
static bool audio_have_tracks(void);
|
||||||
static void audio_reset_buffer(void);
|
static void audio_reset_buffer(void);
|
||||||
|
|
||||||
/* Codec thread */
|
/* Codec thread */
|
||||||
|
extern struct codec_api ci;
|
||||||
static struct event_queue codec_queue;
|
static struct event_queue codec_queue;
|
||||||
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
||||||
IBSS_ATTR;
|
IBSS_ATTR;
|
||||||
|
|
@ -271,6 +269,17 @@ static const char codec_thread_name[] = "codec";
|
||||||
struct thread_entry *codec_thread_p;
|
struct thread_entry *codec_thread_p;
|
||||||
|
|
||||||
/* Voice thread */
|
/* Voice thread */
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
|
extern struct codec_api ci_voice;
|
||||||
|
|
||||||
|
static volatile bool voice_thread_start;
|
||||||
|
static volatile bool voice_is_playing;
|
||||||
|
static volatile bool voice_codec_loaded;
|
||||||
|
static void (*voice_getmore)(unsigned char** start, int* size);
|
||||||
|
static char *voicebuf;
|
||||||
|
static size_t voice_remaining;
|
||||||
|
static struct thread_entry *voice_thread_p = NULL;
|
||||||
|
|
||||||
static struct event_queue voice_queue;
|
static struct event_queue voice_queue;
|
||||||
static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
|
||||||
IBSS_ATTR;
|
IBSS_ATTR;
|
||||||
|
|
@ -286,30 +295,39 @@ static void voice_boost_cpu(bool state);
|
||||||
#else
|
#else
|
||||||
#define voice_boost_cpu(state) do { } while(0)
|
#define voice_boost_cpu(state) do { } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void voice_thread(void);
|
static void voice_thread(void);
|
||||||
|
|
||||||
|
#endif /* PLAYBACK_VOICE */
|
||||||
|
|
||||||
/* --- External interfaces --- */
|
/* --- External interfaces --- */
|
||||||
|
|
||||||
void mp3_play_data(const unsigned char* start, int size,
|
void mp3_play_data(const unsigned char* start, int size,
|
||||||
void (*get_more)(unsigned char** start, int* size))
|
void (*get_more)(unsigned char** start, int* size))
|
||||||
{
|
{
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
static struct voice_info voice_clip;
|
static struct voice_info voice_clip;
|
||||||
voice_clip.callback = get_more;
|
voice_clip.callback = get_more;
|
||||||
voice_clip.buf = (char *)start;
|
voice_clip.buf = (char *)start;
|
||||||
voice_clip.size = size;
|
voice_clip.size = size;
|
||||||
logf("mp3 > voice Q_VOICE_STOP");
|
LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
|
||||||
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
||||||
logf("mp3 > voice Q_VOICE_PLAY");
|
LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
|
||||||
queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip);
|
queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip);
|
||||||
voice_is_playing = true;
|
voice_thread_start = true;
|
||||||
voice_boost_cpu(true);
|
voice_boost_cpu(true);
|
||||||
|
#else
|
||||||
|
(void) start;
|
||||||
|
(void) size;
|
||||||
|
(void) get_more;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp3_play_stop(void)
|
void mp3_play_stop(void)
|
||||||
{
|
{
|
||||||
logf("mp3 > voice Q_VOICE_STOP");
|
#ifdef PLAYBACK_VOICE
|
||||||
|
LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
|
||||||
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp3_pause_done(void)
|
bool mp3_pause_done(void)
|
||||||
|
|
@ -360,8 +378,9 @@ struct mp3entry* audio_current_track(void)
|
||||||
const char *p;
|
const char *p;
|
||||||
static struct mp3entry temp_id3;
|
static struct mp3entry temp_id3;
|
||||||
int cur_idx;
|
int cur_idx;
|
||||||
|
int offset = ci.new_track + wps_offset;
|
||||||
|
|
||||||
cur_idx = track_ridx + ci.new_track;
|
cur_idx = track_ridx + offset;
|
||||||
cur_idx &= MAX_TRACK_MASK;
|
cur_idx &= MAX_TRACK_MASK;
|
||||||
|
|
||||||
if (tracks[cur_idx].taginfo_ready)
|
if (tracks[cur_idx].taginfo_ready)
|
||||||
|
|
@ -369,7 +388,7 @@ struct mp3entry* audio_current_track(void)
|
||||||
|
|
||||||
memset(&temp_id3, 0, sizeof(struct mp3entry));
|
memset(&temp_id3, 0, sizeof(struct mp3entry));
|
||||||
|
|
||||||
filename = playlist_peek(ci.new_track);
|
filename = playlist_peek(offset);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
filename = "No file!";
|
filename = "No file!";
|
||||||
|
|
||||||
|
|
@ -427,10 +446,7 @@ void audio_play(long offset)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (playing)
|
|
||||||
audio_stop();
|
audio_stop();
|
||||||
|
|
||||||
playing = true;
|
|
||||||
LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
|
LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
|
||||||
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
|
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
|
||||||
}
|
}
|
||||||
|
|
@ -440,8 +456,6 @@ void audio_stop(void)
|
||||||
{
|
{
|
||||||
LOGFQUEUE("audio > audio Q_AUDIO_STOP");
|
LOGFQUEUE("audio > audio Q_AUDIO_STOP");
|
||||||
queue_post(&audio_queue, Q_AUDIO_STOP, 0);
|
queue_post(&audio_queue, Q_AUDIO_STOP, 0);
|
||||||
while (playing || audio_codec_loaded)
|
|
||||||
yield();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_pause(void)
|
void audio_pause(void)
|
||||||
|
|
@ -461,10 +475,21 @@ void audio_next(void)
|
||||||
if (global_settings.beep)
|
if (global_settings.beep)
|
||||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||||
|
|
||||||
/* Should be safe to do outside of thread, that way we get
|
if (playlist_check(ci.new_track + wps_offset + 1))
|
||||||
* the instant wps response at least. */
|
{
|
||||||
audio_initiate_track_change(1);
|
LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
|
||||||
// queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1);
|
queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1);
|
||||||
|
/* Keep wps fast while our message travels inside deep playback queues. */
|
||||||
|
wps_offset++;
|
||||||
|
track_changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No more tracks. */
|
||||||
|
if (global_settings.beep)
|
||||||
|
pcmbuf_beep(3000, 300, 2500*global_settings.beep);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_prev(void)
|
void audio_prev(void)
|
||||||
|
|
@ -472,8 +497,21 @@ void audio_prev(void)
|
||||||
if (global_settings.beep)
|
if (global_settings.beep)
|
||||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
||||||
|
|
||||||
audio_initiate_track_change(-1);
|
if (playlist_check(ci.new_track + wps_offset - 1))
|
||||||
// queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1);
|
{
|
||||||
|
LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
|
||||||
|
queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1);
|
||||||
|
/* Keep wps fast while our message travels inside deep playback queues. */
|
||||||
|
wps_offset--;
|
||||||
|
track_changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No more tracks. */
|
||||||
|
if (global_settings.beep)
|
||||||
|
pcmbuf_beep(3000, 300, 2500*global_settings.beep);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_next_dir(void)
|
void audio_next_dir(void)
|
||||||
|
|
@ -598,7 +636,6 @@ void audio_set_crossfade(int enable)
|
||||||
|
|
||||||
/* Restart playback. */
|
/* Restart playback. */
|
||||||
if (was_playing) {
|
if (was_playing) {
|
||||||
playing = true;
|
|
||||||
LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
|
LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
|
||||||
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
|
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
|
||||||
|
|
||||||
|
|
@ -619,7 +656,11 @@ void audio_preinit(void)
|
||||||
playing = false;
|
playing = false;
|
||||||
paused = false;
|
paused = false;
|
||||||
audio_codec_loaded = false;
|
audio_codec_loaded = false;
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
voice_is_playing = false;
|
voice_is_playing = false;
|
||||||
|
voice_thread_start = false;
|
||||||
|
voice_codec_loaded = false;
|
||||||
|
#endif
|
||||||
track_changed = false;
|
track_changed = false;
|
||||||
current_fd = -1;
|
current_fd = -1;
|
||||||
track_buffer_callback = NULL;
|
track_buffer_callback = NULL;
|
||||||
|
|
@ -647,6 +688,7 @@ void audio_init(void)
|
||||||
|
|
||||||
void voice_init(void)
|
void voice_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
if (!filebuf)
|
if (!filebuf)
|
||||||
return; /* Audio buffers not yet set up */
|
return; /* Audio buffers not yet set up */
|
||||||
|
|
||||||
|
|
@ -672,10 +714,12 @@ void voice_init(void)
|
||||||
|
|
||||||
while (!voice_codec_loaded)
|
while (!voice_codec_loaded)
|
||||||
yield();
|
yield();
|
||||||
|
#endif
|
||||||
} /* voice_init */
|
} /* voice_init */
|
||||||
|
|
||||||
void voice_stop(void)
|
void voice_stop(void)
|
||||||
{
|
{
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
/* Messages should not be posted to voice codec queue unless it is the
|
/* Messages should not be posted to voice codec queue unless it is the
|
||||||
current codec or deadlocks happen. This will be addressed globally soon.
|
current codec or deadlocks happen. This will be addressed globally soon.
|
||||||
-- jhMikeS */
|
-- jhMikeS */
|
||||||
|
|
@ -683,14 +727,14 @@ void voice_stop(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mp3_play_stop();
|
mp3_play_stop();
|
||||||
while (voice_is_playing && !queue_empty(&voice_queue))
|
#endif
|
||||||
yield();
|
|
||||||
} /* voice_stop */
|
} /* voice_stop */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* --- Routines called from multiple threads --- */
|
/* --- Routines called from multiple threads --- */
|
||||||
|
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
static void swap_codec(void)
|
static void swap_codec(void)
|
||||||
{
|
{
|
||||||
int my_codec = current_codec;
|
int my_codec = current_codec;
|
||||||
|
|
@ -698,31 +742,34 @@ static void swap_codec(void)
|
||||||
logf("swapping out codec:%d", my_codec);
|
logf("swapping out codec:%d", my_codec);
|
||||||
|
|
||||||
/* Save our current IRAM and DRAM */
|
/* Save our current IRAM and DRAM */
|
||||||
#ifndef SIMULATOR
|
|
||||||
memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN,
|
memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN,
|
||||||
CODEC_IRAM_SIZE);
|
CODEC_IRAM_SIZE);
|
||||||
#endif
|
|
||||||
memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE);
|
memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE);
|
||||||
|
|
||||||
|
/* Release my semaphore */
|
||||||
|
mutex_unlock(&mutex_codecthread);
|
||||||
|
|
||||||
|
/* Loop until the other codec has locked and run */
|
||||||
do {
|
do {
|
||||||
/* Release my semaphore and force a task switch. */
|
/* Release my semaphore and force a task switch. */
|
||||||
mutex_unlock(&mutex_codecthread);
|
|
||||||
yield();
|
yield();
|
||||||
mutex_lock(&mutex_codecthread);
|
|
||||||
/* Loop until the other codec has locked and run */
|
|
||||||
} while (my_codec == current_codec);
|
} while (my_codec == current_codec);
|
||||||
|
|
||||||
|
/* Wait for other codec to unlock */
|
||||||
|
mutex_lock(&mutex_codecthread);
|
||||||
|
|
||||||
|
/* Take control */
|
||||||
current_codec = my_codec;
|
current_codec = my_codec;
|
||||||
|
|
||||||
/* Reload our IRAM and DRAM */
|
/* Reload our IRAM and DRAM */
|
||||||
#ifndef SIMULATOR
|
|
||||||
memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec],
|
memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec],
|
||||||
CODEC_IRAM_SIZE);
|
CODEC_IRAM_SIZE);
|
||||||
#endif
|
|
||||||
invalidate_icache();
|
invalidate_icache();
|
||||||
memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE);
|
memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE);
|
||||||
|
|
||||||
logf("resuming codec:%d", my_codec);
|
logf("resuming codec:%d", my_codec);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void set_filebuf_watermark(int seconds)
|
static void set_filebuf_watermark(int seconds)
|
||||||
{
|
{
|
||||||
|
|
@ -761,6 +808,8 @@ static const char * get_codec_filename(int enc_spec)
|
||||||
|
|
||||||
/* --- Voice thread --- */
|
/* --- Voice thread --- */
|
||||||
|
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
|
|
||||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
static void voice_boost_cpu(bool state)
|
static void voice_boost_cpu(bool state)
|
||||||
{
|
{
|
||||||
|
|
@ -768,8 +817,8 @@ static void voice_boost_cpu(bool state)
|
||||||
|
|
||||||
if (state != voice_cpu_boosted)
|
if (state != voice_cpu_boosted)
|
||||||
{
|
{
|
||||||
cpu_boost(state);
|
|
||||||
voice_cpu_boosted = state;
|
voice_cpu_boosted = state;
|
||||||
|
cpu_boost(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -795,7 +844,7 @@ static bool voice_pcmbuf_insert_split_callback(
|
||||||
while ((dest = pcmbuf_request_voice_buffer(est_output_size,
|
while ((dest = pcmbuf_request_voice_buffer(est_output_size,
|
||||||
&output_size, playing)) == NULL)
|
&output_size, playing)) == NULL)
|
||||||
{
|
{
|
||||||
if (playing)
|
if (playing && audio_codec_loaded)
|
||||||
swap_codec();
|
swap_codec();
|
||||||
else
|
else
|
||||||
yield();
|
yield();
|
||||||
|
|
@ -823,7 +872,7 @@ static bool voice_pcmbuf_insert_split_callback(
|
||||||
if (playing)
|
if (playing)
|
||||||
{
|
{
|
||||||
pcmbuf_mix_voice(output_size);
|
pcmbuf_mix_voice(output_size);
|
||||||
if (pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30)
|
if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded)
|
||||||
swap_codec();
|
swap_codec();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -902,12 +951,18 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
|
||||||
case Q_AUDIO_PLAY:
|
case Q_AUDIO_PLAY:
|
||||||
LOGFQUEUE("voice < Q_AUDIO_PLAY");
|
LOGFQUEUE("voice < Q_AUDIO_PLAY");
|
||||||
if (playing)
|
if (playing)
|
||||||
|
{
|
||||||
|
if (audio_codec_loaded)
|
||||||
swap_codec();
|
swap_codec();
|
||||||
|
else
|
||||||
|
yield();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
|
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
|
||||||
case Q_ENCODER_RECORD:
|
case Q_ENCODER_RECORD:
|
||||||
LOGFQUEUE("voice < Q_ENCODER_RECORD");
|
LOGFQUEUE("voice < Q_ENCODER_RECORD");
|
||||||
|
if (audio_codec_loaded)
|
||||||
swap_codec();
|
swap_codec();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -940,6 +995,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
|
||||||
|
|
||||||
case Q_VOICE_PLAY:
|
case Q_VOICE_PLAY:
|
||||||
LOGFQUEUE("voice < Q_VOICE_PLAY");
|
LOGFQUEUE("voice < Q_VOICE_PLAY");
|
||||||
|
if (!voice_is_playing)
|
||||||
{
|
{
|
||||||
struct voice_info *voice_data;
|
struct voice_info *voice_data;
|
||||||
voice_is_playing = true;
|
voice_is_playing = true;
|
||||||
|
|
@ -949,6 +1005,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
|
||||||
voicebuf = voice_data->buf;
|
voicebuf = voice_data->buf;
|
||||||
voice_getmore = voice_data->callback;
|
voice_getmore = voice_data->callback;
|
||||||
}
|
}
|
||||||
|
goto voice_play_clip;
|
||||||
|
|
||||||
case SYS_TIMEOUT:
|
case SYS_TIMEOUT:
|
||||||
LOGFQUEUE("voice < SYS_TIMEOUT");
|
LOGFQUEUE("voice < SYS_TIMEOUT");
|
||||||
|
|
@ -967,7 +1024,7 @@ voice_play_clip:
|
||||||
voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
|
voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
|
||||||
|
|
||||||
/* If this clip is done */
|
/* If this clip is done */
|
||||||
if (!voice_remaining)
|
if (voice_remaining == 0)
|
||||||
{
|
{
|
||||||
LOGFQUEUE("voice > voice Q_VOICE_STOP");
|
LOGFQUEUE("voice > voice Q_VOICE_STOP");
|
||||||
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
queue_post(&voice_queue, Q_VOICE_STOP, 0);
|
||||||
|
|
@ -1044,6 +1101,7 @@ static void voice_thread(void)
|
||||||
}
|
}
|
||||||
} /* voice_thread */
|
} /* voice_thread */
|
||||||
|
|
||||||
|
#endif /* PLAYBACK_VOICE */
|
||||||
|
|
||||||
/* --- Codec thread --- */
|
/* --- Codec thread --- */
|
||||||
|
|
||||||
|
|
@ -1097,11 +1155,15 @@ static bool codec_pcmbuf_insert_split_callback(
|
||||||
|
|
||||||
pcmbuf_write_complete(output_size);
|
pcmbuf_write_complete(output_size);
|
||||||
|
|
||||||
if (voice_is_playing && pcm_is_playing() &&
|
#ifdef PLAYBACK_VOICE
|
||||||
|
if ((voice_is_playing || voice_thread_start)
|
||||||
|
&& pcm_is_playing() && voice_codec_loaded &&
|
||||||
pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
|
pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
|
||||||
{
|
{
|
||||||
|
voice_thread_start = false;
|
||||||
swap_codec();
|
swap_codec();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
length -= input_size;
|
length -= input_size;
|
||||||
}
|
}
|
||||||
|
|
@ -1684,11 +1746,13 @@ static void codec_thread(void)
|
||||||
case Q_CODEC_LOAD_DISK:
|
case Q_CODEC_LOAD_DISK:
|
||||||
LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
|
LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
|
||||||
audio_codec_loaded = true;
|
audio_codec_loaded = true;
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
if (voice_codec_loaded)
|
if (voice_codec_loaded)
|
||||||
{
|
{
|
||||||
LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
|
LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
|
||||||
queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
|
queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
mutex_lock(&mutex_codecthread);
|
mutex_lock(&mutex_codecthread);
|
||||||
current_codec = CODEC_IDX_AUDIO;
|
current_codec = CODEC_IDX_AUDIO;
|
||||||
ci.stop_codec = false;
|
ci.stop_codec = false;
|
||||||
|
|
@ -1711,11 +1775,13 @@ static void codec_thread(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_codec_loaded = true;
|
audio_codec_loaded = true;
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
if (voice_codec_loaded)
|
if (voice_codec_loaded)
|
||||||
{
|
{
|
||||||
LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
|
LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
|
||||||
queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
|
queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
mutex_lock(&mutex_codecthread);
|
mutex_lock(&mutex_codecthread);
|
||||||
current_codec = CODEC_IDX_AUDIO;
|
current_codec = CODEC_IDX_AUDIO;
|
||||||
ci.stop_codec = false;
|
ci.stop_codec = false;
|
||||||
|
|
@ -1729,11 +1795,13 @@ static void codec_thread(void)
|
||||||
case Q_ENCODER_LOAD_DISK:
|
case Q_ENCODER_LOAD_DISK:
|
||||||
LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
|
LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
|
||||||
audio_codec_loaded = false;
|
audio_codec_loaded = false;
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
|
if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
|
||||||
{
|
{
|
||||||
LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
|
LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
|
||||||
queue_post(&voice_queue, Q_ENCODER_RECORD, NULL);
|
queue_post(&voice_queue, Q_ENCODER_RECORD, NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
mutex_lock(&mutex_codecthread);
|
mutex_lock(&mutex_codecthread);
|
||||||
current_codec = CODEC_IDX_AUDIO;
|
current_codec = CODEC_IDX_AUDIO;
|
||||||
ci.stop_codec = false;
|
ci.stop_codec = false;
|
||||||
|
|
@ -1747,8 +1815,10 @@ static void codec_thread(void)
|
||||||
LOGFQUEUE("codec < SYS_USB_CONNECTED");
|
LOGFQUEUE("codec < SYS_USB_CONNECTED");
|
||||||
queue_clear(&codec_queue);
|
queue_clear(&codec_queue);
|
||||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||||
if (voice_codec_loaded)
|
#ifdef PLAYBACK_VOICE
|
||||||
|
if(voice_codec_loaded)
|
||||||
swap_codec();
|
swap_codec();
|
||||||
|
#endif
|
||||||
usb_wait_for_disconnect(&codec_queue);
|
usb_wait_for_disconnect(&codec_queue);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2199,7 +2269,6 @@ static bool audio_loadcodec(bool start_play)
|
||||||
ci.id3 = &cur_ti->id3;
|
ci.id3 = &cur_ti->id3;
|
||||||
ci.taginfo_ready = &cur_ti->taginfo_ready;
|
ci.taginfo_ready = &cur_ti->taginfo_ready;
|
||||||
ci.curpos = 0;
|
ci.curpos = 0;
|
||||||
playing = true;
|
|
||||||
LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
|
LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
|
||||||
queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
|
queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2261,8 +2330,6 @@ static bool audio_loadcodec(bool start_play)
|
||||||
buf_widx -= filebuflen;
|
buf_widx -= filebuflen;
|
||||||
|
|
||||||
tracks[track_widx].codecsize += rc;
|
tracks[track_widx].codecsize += rc;
|
||||||
|
|
||||||
audio_yield_codecs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tracks[track_widx].has_codec = true;
|
tracks[track_widx].has_codec = true;
|
||||||
|
|
@ -2941,9 +3008,6 @@ static void audio_stop_playback(void)
|
||||||
(playlist_end && ci.stop_codec)?NULL:audio_current_track());
|
(playlist_end && ci.stop_codec)?NULL:audio_current_track());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (voice_is_playing && !queue_empty(&voice_queue))
|
|
||||||
yield();
|
|
||||||
|
|
||||||
filebufused = 0;
|
filebufused = 0;
|
||||||
playing = false;
|
playing = false;
|
||||||
filling = false;
|
filling = false;
|
||||||
|
|
@ -2968,7 +3032,6 @@ static void audio_play_start(size_t offset)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Wait for any previously playing audio to flush - TODO: Not necessary? */
|
/* Wait for any previously playing audio to flush - TODO: Not necessary? */
|
||||||
while (audio_codec_loaded)
|
|
||||||
audio_stop_codec_flush();
|
audio_stop_codec_flush();
|
||||||
|
|
||||||
track_changed = true;
|
track_changed = true;
|
||||||
|
|
@ -2977,6 +3040,7 @@ static void audio_play_start(size_t offset)
|
||||||
playing = true;
|
playing = true;
|
||||||
ci.new_track = 0;
|
ci.new_track = 0;
|
||||||
ci.seek_time = 0;
|
ci.seek_time = 0;
|
||||||
|
wps_offset = 0;
|
||||||
|
|
||||||
if (current_fd >= 0)
|
if (current_fd >= 0)
|
||||||
{
|
{
|
||||||
|
|
@ -3057,15 +3121,9 @@ static void audio_new_playlist(void)
|
||||||
|
|
||||||
static void audio_initiate_track_change(long direction)
|
static void audio_initiate_track_change(long direction)
|
||||||
{
|
{
|
||||||
if (playlist_check(direction))
|
|
||||||
{
|
|
||||||
playlist_end = false;
|
playlist_end = false;
|
||||||
/* Flag track changed immediately so wps can update instantly.
|
|
||||||
* No need to wait for disk to spin up or message to travel
|
|
||||||
* through the deep queues as this info is only for the wps. */
|
|
||||||
track_changed = true;
|
|
||||||
ci.new_track += direction;
|
ci.new_track += direction;
|
||||||
}
|
wps_offset -= direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_initiate_dir_change(long direction)
|
static void audio_initiate_dir_change(long direction)
|
||||||
|
|
@ -3090,10 +3148,8 @@ static void audio_reset_buffer(void)
|
||||||
/* Allow 2 codecs at end of file buffer */
|
/* Allow 2 codecs at end of file buffer */
|
||||||
filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE);
|
filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE);
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
|
||||||
iram_buf[0] = &filebuf[filebuflen];
|
iram_buf[0] = &filebuf[filebuflen];
|
||||||
iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
|
iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
|
||||||
#endif
|
|
||||||
dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2];
|
dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2];
|
||||||
dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
|
dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
|
||||||
}
|
}
|
||||||
|
|
@ -3102,10 +3158,8 @@ static void audio_reset_buffer(void)
|
||||||
/* Allow for 1 codec at end of file buffer */
|
/* Allow for 1 codec at end of file buffer */
|
||||||
filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE;
|
filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE;
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
|
||||||
iram_buf[0] = &filebuf[filebuflen];
|
iram_buf[0] = &filebuf[filebuflen];
|
||||||
iram_buf[1] = NULL;
|
iram_buf[1] = NULL;
|
||||||
#endif
|
|
||||||
dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE];
|
dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE];
|
||||||
dram_buf[1] = NULL;
|
dram_buf[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -3129,7 +3183,10 @@ static void audio_test_track_changed_event(struct mp3entry *id3)
|
||||||
|
|
||||||
static void audio_playback_init(void)
|
static void audio_playback_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
static bool voicetagtrue = true;
|
static bool voicetagtrue = true;
|
||||||
|
static struct mp3entry id3_voice;
|
||||||
|
#endif
|
||||||
struct event ev;
|
struct event ev;
|
||||||
|
|
||||||
logf("playback api init");
|
logf("playback api init");
|
||||||
|
|
@ -3162,6 +3219,7 @@ static void audio_playback_init(void)
|
||||||
ci.discard_codec = codec_discard_codec_callback;
|
ci.discard_codec = codec_discard_codec_callback;
|
||||||
|
|
||||||
/* Initialize voice codec api. */
|
/* Initialize voice codec api. */
|
||||||
|
#ifdef PLAYBACK_VOICE
|
||||||
memcpy(&ci_voice, &ci, sizeof(struct codec_api));
|
memcpy(&ci_voice, &ci, sizeof(struct codec_api));
|
||||||
memset(&id3_voice, 0, sizeof(struct mp3entry));
|
memset(&id3_voice, 0, sizeof(struct mp3entry));
|
||||||
ci_voice.read_filebuf = voice_filebuf_callback;
|
ci_voice.read_filebuf = voice_filebuf_callback;
|
||||||
|
|
@ -3182,6 +3240,7 @@ static void audio_playback_init(void)
|
||||||
ci_voice.id3 = &id3_voice;
|
ci_voice.id3 = &id3_voice;
|
||||||
id3_voice.frequency = 11200;
|
id3_voice.frequency = 11200;
|
||||||
id3_voice.length = 1000000L;
|
id3_voice.length = 1000000L;
|
||||||
|
#endif
|
||||||
|
|
||||||
codec_thread_p = create_thread(codec_thread, codec_stack,
|
codec_thread_p = create_thread(codec_thread, codec_stack,
|
||||||
sizeof(codec_stack),
|
sizeof(codec_stack),
|
||||||
|
|
@ -3288,8 +3347,6 @@ static void audio_thread(void)
|
||||||
case Q_AUDIO_DIR_SKIP:
|
case Q_AUDIO_DIR_SKIP:
|
||||||
LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
|
LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
|
||||||
playlist_end = false;
|
playlist_end = false;
|
||||||
if (global_settings.beep)
|
|
||||||
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
|
|
||||||
audio_initiate_dir_change((long)ev.data);
|
audio_initiate_dir_change((long)ev.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue