mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
talk: Add debug menu entry to view statistics about talk engine.
This engine includes voicefile, memory usage and cache hits/misses for TALK_PARTIAL_LOAD. Change-Id: I331981ddda39ea30c57b4b74504accb3c556c3b9
This commit is contained in:
parent
57000b513b
commit
dac40fdd60
3 changed files with 135 additions and 2 deletions
|
@ -131,6 +131,8 @@
|
||||||
#include "rds.h"
|
#include "rds.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "talk.h"
|
||||||
|
|
||||||
/*---------------------------------------------------*/
|
/*---------------------------------------------------*/
|
||||||
/* SPECIAL DEBUG STUFF */
|
/* SPECIAL DEBUG STUFF */
|
||||||
/*---------------------------------------------------*/
|
/*---------------------------------------------------*/
|
||||||
|
@ -2130,6 +2132,67 @@ static bool dbg_scrollwheel(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const char* dbg_talk_get_name(int selected_item, void *data,
|
||||||
|
char *buffer, size_t buffer_len)
|
||||||
|
{
|
||||||
|
struct talk_debug_data *talk_data = data;
|
||||||
|
switch(selected_item)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (talk_data)
|
||||||
|
snprintf(buffer, buffer_len, "Current voice file: %s",
|
||||||
|
talk_data->voicefile);
|
||||||
|
else
|
||||||
|
buffer = "No voice information available";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
snprintf(buffer, buffer_len, "Number of (empty) clips in voice file: (%d) %d",
|
||||||
|
talk_data->num_empty_clips, talk_data->num_clips);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
snprintf(buffer, buffer_len, "Min/Avg/Max size of clips: %d / %d / %d",
|
||||||
|
talk_data->min_clipsize, talk_data->avg_clipsize, talk_data->max_clipsize);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
snprintf(buffer, buffer_len, "Memory allocated: %ld.%02ld KB",
|
||||||
|
talk_data->memory_allocated / 1024, talk_data->memory_allocated % 1024);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
snprintf(buffer, buffer_len, "Memory used: %ld.%02ld KB",
|
||||||
|
talk_data->memory_used / 1024, talk_data->memory_used % 1024);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
snprintf(buffer, buffer_len, "Number of clips in cache: %d",
|
||||||
|
talk_data->cached_clips);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
snprintf(buffer, buffer_len, "Cache hits / misses: %d / %d",
|
||||||
|
talk_data->cache_hits, talk_data->cache_misses);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buffer = "TODO";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dbg_talk(void)
|
||||||
|
{
|
||||||
|
struct simplelist_info list;
|
||||||
|
struct talk_debug_data data;
|
||||||
|
if (talk_get_debug_data(&data))
|
||||||
|
simplelist_info_init(&list, "Voice Information:", 7, &data);
|
||||||
|
else
|
||||||
|
simplelist_info_init(&list, "Voice Information:", 1, NULL);
|
||||||
|
list.scroll_all = true;
|
||||||
|
list.hide_selection = true;
|
||||||
|
list.timeout = HZ;
|
||||||
|
list.get_name = dbg_talk_get_name;
|
||||||
|
|
||||||
|
return simplelist_show_list(&list);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_USBSTACK
|
#ifdef HAVE_USBSTACK
|
||||||
#if defined(ROCKBOX_HAS_LOGF) && defined(USB_ENABLE_SERIAL)
|
#if defined(ROCKBOX_HAS_LOGF) && defined(USB_ENABLE_SERIAL)
|
||||||
static bool toggle_usb_serial(void)
|
static bool toggle_usb_serial(void)
|
||||||
|
@ -2361,6 +2424,7 @@ static const struct {
|
||||||
&& !defined(IPOD_MINI) && !defined(SIMULATOR))
|
&& !defined(IPOD_MINI) && !defined(SIMULATOR))
|
||||||
{"Debug scrollwheel", dbg_scrollwheel },
|
{"Debug scrollwheel", dbg_scrollwheel },
|
||||||
#endif
|
#endif
|
||||||
|
{"Talk engine stats", dbg_talk },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int menu_action_callback(int btn, struct gui_synclist *lists)
|
static int menu_action_callback(int btn, struct gui_synclist *lists)
|
||||||
|
|
61
apps/talk.c
61
apps/talk.c
|
@ -123,6 +123,7 @@ static uint8_t clip_age[QUEUE_SIZE];
|
||||||
#if QUEUE_SIZE > 255
|
#if QUEUE_SIZE > 255
|
||||||
# error clip_age[] type too small
|
# error clip_age[] type too small
|
||||||
#endif
|
#endif
|
||||||
|
static int cache_hits, cache_misses;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Multiple thumbnails can be loaded back-to-back in this buffer. */
|
/* Multiple thumbnails can be loaded back-to-back in this buffer. */
|
||||||
|
@ -165,6 +166,7 @@ struct queue_entry /* one entry of the internal queue */
|
||||||
|
|
||||||
static struct queue_entry queue[QUEUE_SIZE]; /* queue of scheduled clips */
|
static struct queue_entry queue[QUEUE_SIZE]; /* queue of scheduled clips */
|
||||||
|
|
||||||
|
#define DEFAULT_VOICE_LANG "english"
|
||||||
|
|
||||||
/***************** Private implementation *****************/
|
/***************** Private implementation *****************/
|
||||||
|
|
||||||
|
@ -294,7 +296,7 @@ static struct buflib_callbacks index_ops = {
|
||||||
static int open_voicefile(void)
|
static int open_voicefile(void)
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[64];
|
||||||
char* p_lang = "english"; /* default */
|
char* p_lang = DEFAULT_VOICE_LANG; /* default */
|
||||||
|
|
||||||
if ( global_settings.lang_file[0] &&
|
if ( global_settings.lang_file[0] &&
|
||||||
global_settings.lang_file[0] != 0xff )
|
global_settings.lang_file[0] != 0xff )
|
||||||
|
@ -344,6 +346,7 @@ static int get_clip(long id, long* p_size)
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
int fd, idx = 0;
|
int fd, idx = 0;
|
||||||
unsigned char *voicebuf;
|
unsigned char *voicebuf;
|
||||||
|
cache_misses++;
|
||||||
if (id == VOICE_PAUSE) {
|
if (id == VOICE_PAUSE) {
|
||||||
idx = QUEUE_SIZE; /* we keep VOICE_PAUSE loaded */
|
idx = QUEUE_SIZE; /* we keep VOICE_PAUSE loaded */
|
||||||
} else {
|
} else {
|
||||||
|
@ -397,6 +400,7 @@ static int get_clip(long id, long* p_size)
|
||||||
else
|
else
|
||||||
{ /* clip is in memory already */
|
{ /* clip is in memory already */
|
||||||
/* Find where it was loaded */
|
/* Find where it was loaded */
|
||||||
|
cache_hits++;
|
||||||
if (id == VOICE_PAUSE) {
|
if (id == VOICE_PAUSE) {
|
||||||
retval = QUEUE_SIZE * max_clipsize;
|
retval = QUEUE_SIZE * max_clipsize;
|
||||||
} else {
|
} else {
|
||||||
|
@ -583,7 +587,6 @@ load_err_free:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* called in ISR context (on HWCODEC) if mp3 data got consumed */
|
/* called in ISR context (on HWCODEC) if mp3 data got consumed */
|
||||||
static void mp3_callback(const void** start, size_t* size)
|
static void mp3_callback(const void** start, size_t* size)
|
||||||
{
|
{
|
||||||
|
@ -1456,3 +1459,57 @@ void talk_time(const struct tm *tm, bool enqueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_RTC */
|
#endif /* CONFIG_RTC */
|
||||||
|
|
||||||
|
|
||||||
|
bool talk_get_debug_data(struct talk_debug_data *data)
|
||||||
|
{
|
||||||
|
char* p_lang = DEFAULT_VOICE_LANG; /* default */
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(*data));
|
||||||
|
|
||||||
|
if (!has_voicefile || index_handle <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff)
|
||||||
|
p_lang = (char *)global_settings.lang_file;
|
||||||
|
|
||||||
|
struct clip_entry *clips = core_get_data(index_handle);
|
||||||
|
#ifdef TALK_PARTIAL_LOAD
|
||||||
|
int cached = 0;
|
||||||
|
#endif
|
||||||
|
int real_clips = 0;
|
||||||
|
|
||||||
|
strlcpy(data->voicefile, p_lang, sizeof(data->voicefile));
|
||||||
|
data->num_clips = voicefile.id1_max + voicefile.id2_max;
|
||||||
|
data->avg_clipsize = data->max_clipsize = 0;
|
||||||
|
data->min_clipsize = INT_MAX;
|
||||||
|
for(int i = 0; i < data->num_clips; i++)
|
||||||
|
{
|
||||||
|
int size = clips[i].size & (~LOADED_MASK);
|
||||||
|
if (!size) continue;
|
||||||
|
real_clips += 1;
|
||||||
|
if (size < data->min_clipsize)
|
||||||
|
data->min_clipsize = size;
|
||||||
|
if (size > data->max_clipsize)
|
||||||
|
data->max_clipsize = size;
|
||||||
|
data->avg_clipsize += size;
|
||||||
|
#ifdef TALK_PARTIAL_LOAD
|
||||||
|
if (clips[i].size & LOADED_MASK)
|
||||||
|
cached++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
data->avg_clipsize /= real_clips;
|
||||||
|
data->num_empty_clips = data->num_clips - real_clips;
|
||||||
|
data->memory_allocated = voicefile_size + size_for_thumbnail;
|
||||||
|
data->memory_used = voicefile_size + thumbnail_buf_used;
|
||||||
|
#ifdef TALK_PARTIAL_LOAD
|
||||||
|
data->cached_clips = cached;
|
||||||
|
data->cache_hits = cache_hits;
|
||||||
|
data->cache_misses = cache_misses;
|
||||||
|
#else
|
||||||
|
data->cached_clips = real_clips;
|
||||||
|
data->cache_hits = data->cache_misses = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
12
apps/talk.h
12
apps/talk.h
|
@ -162,4 +162,16 @@ int talk_idarray(const long *idarray, bool enqueue);
|
||||||
} \
|
} \
|
||||||
}while(0)
|
}while(0)
|
||||||
|
|
||||||
|
struct talk_debug_data {
|
||||||
|
char voicefile[32];
|
||||||
|
long memory_allocated, memory_used;
|
||||||
|
int num_clips, num_empty_clips;
|
||||||
|
int min_clipsize, avg_clipsize, max_clipsize;
|
||||||
|
int cached_clips;
|
||||||
|
int cache_hits;
|
||||||
|
int cache_misses;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool talk_get_debug_data(struct talk_debug_data *data);
|
||||||
|
|
||||||
#endif /* __TALK_H__ */
|
#endif /* __TALK_H__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue