Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce voice RAM and ROM needs #665

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
be3c202
remove voice map and read voice.ini on demand
TheRealMoeder Jan 30, 2019
63a386a
Handle timers in on demand voice.ini reading
TheRealMoeder Feb 1, 2019
a195aa1
Cleanup and fix linter errors
TheRealMoeder Feb 1, 2019
d3ee876
Correct voice file count and small rom save
TheRealMoeder Feb 3, 2019
ea09e02
fix build error when disabling voice-menu
TheRealMoeder Feb 3, 2019
30ede8d
Reduce function calls in MIXER_ApplyMixers
TheRealMoeder Feb 3, 2019
2724b8c
remove unnecessary pp line
TheRealMoeder Feb 3, 2019
da6c5cb
use ptr to save rom in voiceconfig
TheRealMoeder Feb 3, 2019
f1cf456
fix linter error
TheRealMoeder Feb 3, 2019
f17b917
save rom in telemetry.c for voice
TheRealMoeder Feb 3, 2019
4d36b63
fix linter errors
TheRealMoeder Feb 3, 2019
8617d34
move if to switch statement to save rom
TheRealMoeder Feb 3, 2019
ad40cf0
fix error
TheRealMoeder Feb 3, 2019
327081e
fix error
TheRealMoeder Feb 3, 2019
0998b41
Fix timer alarms
TheRealMoeder Feb 3, 2019
f09c27a
Remove old trim button voice logic. The same can now be achieved with…
TheRealMoeder Feb 3, 2019
55381d9
Increase custom voice limit
TheRealMoeder Feb 4, 2019
4cf14b7
Limit scope of some AUDIO functions
TheRealMoeder Feb 4, 2019
84a1f1c
Fix linter errors
TheRealMoeder Feb 4, 2019
1d8f208
small improvment of debug messages
TheRealMoeder Feb 7, 2019
5bdcebf
Reduce AUDIO_VoiceAvailable calls
TheRealMoeder Feb 7, 2019
ffd8c30
Optimize MUSIC_PlayValue
TheRealMoeder Feb 7, 2019
0fae090
Remove MUSIC_GetTimerAlarm as it is only called once
TheRealMoeder Feb 7, 2019
3914245
fix lint error
TheRealMoeder Feb 7, 2019
7147d6a
avoid preprocessor ifs
TheRealMoeder Feb 8, 2019
682a87e
address review
TheRealMoeder Feb 18, 2019
8583924
fix merge errors
TheRealMoeder Feb 20, 2019
529de21
Allow empty custom music section
TheRealMoeder Mar 8, 2019
7ce4bc1
Allow empty custom voice section #2
TheRealMoeder Mar 8, 2019
ed12dc7
Allow empty custom section in voice.ini
TheRealMoeder Mar 8, 2019
304060c
Fix error
TheRealMoeder Mar 8, 2019
336532a
Fix screenshot test
TheRealMoeder Mar 8, 2019
3785845
Fix lint error
TheRealMoeder Mar 8, 2019
0416d69
remove voice config from screenshot tests
TheRealMoeder Mar 12, 2019
361bfd2
address review
TheRealMoeder Mar 12, 2019
942a33c
fix lint error
TheRealMoeder Mar 12, 2019
90d8d2f
Merge branch 'master' into voice_diet2
TheRealMoeder Mar 24, 2019
db82aef
fix merge error
TheRealMoeder Mar 24, 2019
15ddfeb
Merge remote-tracking branch 'upstream/master' into voice_diet2
TheRealMoeder Apr 8, 2019
6dfc826
Merge remote-tracking branch 'upstream/master' into voice_diet2
TheRealMoeder Apr 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions doc/Extended-audio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ A. Voice Feedback on the following are supported. For additional details, refer
- Changing Switch Positions.
- Turning of Auxiliary Knobs.
Different voice files can be specified for turning up & turning down of knobs.
- Trim buttons as virtual switches.
Different voice files can be specified for the same trim button when used as
Momentary or Toggle switch.

B. Following options have been added to media/sound.ini file.
1) Specify a different playback device for each alert message.
Expand Down
12 changes: 11 additions & 1 deletion src/config/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "tx.h"
#include "music.h"
#include "extended_audio.h"
#include "voice.h"

#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -1076,7 +1077,8 @@ int assign_int(void* ptr, const struct struct_map *map, int map_size)

if (MATCH_SECTION(SECTION_VOICE)) {
u16 val = atoi(value);
if(val>MAX_VOICEMAP_ENTRIES-1 || voice_map[val].duration == 0 || val < CUSTOM_ALARM_ID) {
CONFIG_VoiceParse(val);
if (current_voice_mapping.duration == 0 || val < CUSTOM_ALARM_ID) {
printf("%s: Music %s not found in voice.ini or below ID %d\n", section, value, CUSTOM_ALARM_ID);
return 0;
}
Expand Down Expand Up @@ -1106,6 +1108,8 @@ int assign_int(void* ptr, const struct struct_map *map, int map_size)
for (int i = 0; i < NUM_TIMERS; i++) {
if (MATCH_KEY(VOICE_TIMER[i])) {
m->voice.timer[i].music = val;
CONFIG_VoiceParse(MUSIC_ALARM1+i);
m->timer[i].duration = current_voice_mapping.duration;
return 1;
}
}
Expand Down Expand Up @@ -1494,6 +1498,12 @@ static void clear_model(u8 full)
}
Model.ppmin_centerpw = 1500;
Model.ppmin_deltapw = 400;
#if HAS_EXTENDED_AUDIO
for (int i = 0; i < NUM_TIMERS; i++) {
TheRealMoeder marked this conversation as resolved.
Show resolved Hide resolved
CONFIG_VoiceParse(MUSIC_ALARM1 + i);
Model.timer[i].duration = current_voice_mapping.duration;
}
#endif
}

u8 CONFIG_ReadModel(u8 model_num) {
Expand Down
2 changes: 1 addition & 1 deletion src/config/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ void CONFIG_LoadTx()
CONFIG_LoadHardware();
CONFIG_IniParse("tx.ini", ini_handler, (void *)&Transmitter);
crc32 = Crc(&Transmitter, sizeof(Transmitter));
#if HAS_EXTENDED_AUDIO
#if HAS_MUSIC_CONFIG
CONFIG_VoiceParse(MAX_VOICEMAP_ENTRIES);
TheRealMoeder marked this conversation as resolved.
Show resolved Hide resolved
#endif
return;
Expand Down
48 changes: 20 additions & 28 deletions src/config/voice.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const char SECTION_VOICE_CUSTOM[] = "custom";

static int ini_handler(void* user, const char* section, const char* name, const char* value)
{
// ini_handler returns a requested mp3 label passed at *user to tempstring
(void) section;
u16 req_id = *((long*)user);
u16 id = atoi(name);
const char* ptr = value;
Expand All @@ -47,32 +47,24 @@ static int ini_handler(void* user, const char* section, const char* name, const
duration = atoi(ptr + 1);
}

#if HAS_MUSIC_CONFIG
if ( k && (req_id != MAX_VOICEMAP_ENTRIES) && (req_id == id) ) {
strlcpy(tempstring, value, k+1);
tempstring[MAX_VOICE_LABEL] = '\0'; // limit label length
current_voice_mapping.duration = duration;
if (HAS_MUSIC_CONFIG)
strlcpy(tempstring, value, k+1); // return a requested mp3 label passed at *user to tempstring
TheRealMoeder marked this conversation as resolved.
Show resolved Hide resolved
return 1;
}
#endif
if ( req_id == MAX_VOICEMAP_ENTRIES ) {
if (MATCH_SECTION(SECTION_VOICE_GLOBAL)) {
for (int i = 0; i < CUSTOM_ALARM_ID; i++) {
snprintf(tempstring, 4, "%d", i);
if (MATCH_KEY(tempstring)) {
voice_map[i].duration = duration;
voice_map[i].id = i;
return 1;
}
if (HAS_MUSIC_CONFIG) {
if ( req_id == MAX_VOICEMAP_ENTRIES ) {
if (MATCH_SECTION(SECTION_VOICE_GLOBAL)) {
voice_map_entries = 0;
}
if (MATCH_SECTION(SECTION_VOICE_CUSTOM)) {
// Initial count of custom voicemap entries
voice_map_entries++;
return 1;
}
return 0;
}
if (MATCH_SECTION(SECTION_VOICE_CUSTOM)) {
voice_map[voice_map_entries].duration = duration;
voice_map[voice_map_entries].id = id;
voice_map_entries++;
return 1;
}
printf("Unknown entry in voice.ini: %s\n", value);
return 0;
}
return 1; // voice label ignored
}
Expand All @@ -95,16 +87,16 @@ const char* CONFIG_VoiceParse(unsigned id)
char filename[] = "media/voice.ini";
#endif
if (id == MAX_VOICEMAP_ENTRIES) { // initial parse of voice.ini
voice_map_entries = CUSTOM_ALARM_ID; // Reserve space in map for global alerts
if (CONFIG_IniParse(filename, ini_handler, &id)) {
printf("Failed to parse voice.ini\n");
Transmitter.audio_player = AUDIO_NONE; // disable external voice output
if (CONFIG_IniParse(filename, ini_handler, &id))
tempstring[0] = '\0';
if (voice_map_entries < 0) {
printf("Failed to parse voice.ini\n");
Transmitter.audio_player = AUDIO_NONE; // disable external voice when no global voices are found in voice.ini
}
}
if ( (id < MAX_VOICEMAP_ENTRIES) && (id >= CUSTOM_ALARM_ID) ) {
if ( (id < MAX_VOICEMAP_ENTRIES) ) {
if (CONFIG_IniParse(filename, ini_handler, &id)) {
// ini handler will return tempstring with label of id
// ini handler will return tempstring with label of id and fill current_voice_mapping
}
}
return tempstring;
Expand Down
2 changes: 1 addition & 1 deletion src/config/voice.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const char* CONFIG_VoiceParse();
const char* CONFIG_VoiceParse(unsigned id);
TheRealMoeder marked this conversation as resolved.
Show resolved Hide resolved
66 changes: 34 additions & 32 deletions src/extended_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "music.h"
#include "config/tx.h"
#include "config/model.h"
#include "config/voice.h"
#include "extended_audio.h"
#include "stdlib.h"

Expand All @@ -25,9 +26,9 @@
#endif // EMULATOR

#if HAS_EXTENDED_AUDIO
u16 voice_map_entries;
struct VoiceMap voice_map[MAX_VOICEMAP_ENTRIES];
u16 audio_queue[AUDIO_QUEUE_LENGTH];
s16 voice_map_entries = -1;
TheRealMoeder marked this conversation as resolved.
Show resolved Hide resolved
struct QueueEntry current_voice_mapping;
struct QueueEntry audio_queue[AUDIO_QUEUE_LENGTH];
u8 next_audio;
u8 num_audio;
u32 audio_queue_time;
Expand Down Expand Up @@ -68,51 +69,48 @@ void AUDIO_Init() {

#ifndef EMULATOR
// Send a block of len bytes to the Audio device.
void
AUDIO_Send(u8 *data, int len) {
static void AUDIO_Send(u8 *data, int len) {
void AUDIO_send_char(char c);
for (u16 iter = 0; iter < len; iter += 1) {
AUDIO_send_char(data[iter]);
}
}

// Send a string to the Audio device.
void
AUDIO_Print(char *string) {
static void AUDIO_Print(char *string) {
AUDIO_Send((u8 *)string, strlen(string));
}
#endif // EMULATOR

void u16ToArray(u16 value, u8 *array){
static void u16ToArray(u16 value, u8 *array) {
*array = (u8)(value>>8);
*(array+1) = (u8)value;
}

// generate Checksum for DFPlyer commands
u16 AUDIO_CalculateChecksum(u8 *buffer) {
static u16 AUDIO_CalculateChecksum(u8 *buffer) {
u16 sum = 0;
for (int i=1; i < 7; i += 1)
sum += buffer[i];
return -sum;
}

// Generate a string to play.
int AUDIO_Play(u16 music) {

static int AUDIO_Play(u16 id) {
// If we are just playing beeps....
if (music == MUSIC_KEY_PRESSING || music == MUSIC_MAXLEN) {
if (id == MUSIC_KEY_PRESSING || id == MUSIC_MAXLEN) {
printf("Voice: beep only\n");
return 0;
}
printf("Voice: Playing mp3 #%d\n", voice_map[music].id);
printf("Voice: Playing mp3 #%d\n", id);

#ifdef EMULATOR // On emulators call mpg123 to play mp3s
char cmd[70];
u16 vol_val = Transmitter.audio_vol * 32786/10;
#ifdef _WIN32
sprintf(cmd, "start /B ..\\..\\mpg123 -f %d -q ..\\..\\mp3\\%04d*.mp3 > nul 2>&1", vol_val, voice_map[music].id);
snprintf(cmd, sizeof(cmd), "start /B ..\\..\\mpg123 -f %d -q ..\\..\\mp3\\%04d*.mp3 > nul 2>&1", vol_val, id);
#else
sprintf(cmd, "mpg123 -f %d -q ../../mp3/%04d*.mp3 > /dev/null 2>&1 &", vol_val, voice_map[music].id);
snprintf(cmd, sizeof(cmd), "mpg123 -f %d -q ../../mp3/%04d*.mp3 > /dev/null 2>&1 &", vol_val, id);
#endif // _WIN32
system(cmd);
return 1;
Expand All @@ -125,14 +123,14 @@ int AUDIO_Play(u16 music) {
case AUDIO_NONE: return 0; // Play beeps...
case AUDIO_AUDIOFX: {
char buffer[5];
snprintf(buffer, sizeof(buffer), "#%d\n", voice_map[music].id);
snprintf(buffer, sizeof(buffer), "#%d\n", id);
AUDIO_Print(buffer);
break;
}
case AUDIO_DF_PLAYER:
// Fill in track number and checksum
player_buffer[3] = 0x12;
u16ToArray(voice_map[music].id, player_buffer+5);
u16ToArray(id, player_buffer+5);
u16ToArray(AUDIO_CalculateChecksum(player_buffer), player_buffer+7);
AUDIO_Send(player_buffer, sizeof(player_buffer));
break;
Expand Down Expand Up @@ -171,57 +169,61 @@ void AUDIO_SetVolume() {
}
#endif
}
static void AUDIO_ResetQueue() {
num_audio = 0;
next_audio = 0;
printf("Voice: Queue finished, resetting.\n");
}

void AUDIO_CheckQueue() {
u32 t = CLOCK_getms();
if (next_audio < num_audio) {
if (t > audio_queue_time) {
AUDIO_Play(audio_queue[next_audio]);
audio_queue_time = CLOCK_getms() + voice_map[audio_queue[next_audio]].duration;
AUDIO_Play(audio_queue[next_audio].id);
audio_queue_time = CLOCK_getms() + audio_queue[next_audio].duration;
next_audio++;
}
} else if (num_audio && t > audio_queue_time) {
printf("Voice: Queue finished, resetting.\n");
num_audio = 0;
next_audio = 0;
AUDIO_ResetQueue();
AUDIO_SetVolume();
}
}

int AUDIO_VoiceAvailable() {
static int AUDIO_VoiceAvailable() {
#ifndef _DEVO12_TARGET_H_
#if HAS_AUDIO_UART
if ( !Transmitter.audio_uart && (PPMin_Mode() || Model.protocol == PROTOCOL_PPM) ) { // don't send play command when using PPM port
#else
if ( PPMin_Mode() || Model.protocol == PROTOCOL_PPM ) { // don't send play command when using PPM port
#endif
printf("Voice: PPM port in use\n");
num_audio = 0; // Reset queue when audio not available
next_audio = 0;
AUDIO_ResetQueue();
return 0;
}
#endif // _DEVO12_TARGET_H_

if ( (Transmitter.audio_player == AUDIO_NONE) || (Transmitter.audio_player == AUDIO_DISABLED) || !Transmitter.audio_vol ) {
num_audio = 0; // Reset queue when audio not available
next_audio = 0;
AUDIO_ResetQueue();
return 0;
}

return 1;
}

int AUDIO_AddQueue(u16 music) {
if (num_audio == AUDIO_QUEUE_LENGTH) {
printf("Voice: Queue full, cannot add new mp3 #%d\n",music);
if (!AUDIO_VoiceAvailable() || num_audio == AUDIO_QUEUE_LENGTH) {
printf("Voice: queue full or voice not available, cannot add new mp3 #%d\n", music);
return 0;
}
if (!voice_map[music].duration) {
CONFIG_VoiceParse(music);
if (!current_voice_mapping.duration) {
printf("Voice: mp3 length is zero\n");
return 0;
}

audio_queue[num_audio++] = music;
audio_queue[num_audio].duration = current_voice_mapping.duration;
audio_queue[num_audio].id = music;
printf("Voice: added ID %d with duration %d to queue position %d.\n", music, current_voice_mapping.duration, num_audio);
num_audio++;
return 1;
}

Expand Down
5 changes: 2 additions & 3 deletions src/extended_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
#define AUDIO_QUEUE_LENGTH 20 // arbitraty chosen, do we need more?

void AUDIO_Init();
int AUDIO_Play(u16 music);
void AUDIO_SetVolume();
void AUDIO_CheckQueue();
int AUDIO_AddQueue(u16 music);
int AUDIO_VoiceAvailable();

extern u16 audio_queue[AUDIO_QUEUE_LENGTH];
extern struct QueueEntry audio_queue[AUDIO_QUEUE_LENGTH];
extern struct QueueEntry current_voice_mapping;
extern u8 next_audio;
extern u8 num_audio;
extern u32 audio_queue_time;
Expand Down
5 changes: 0 additions & 5 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,12 @@ void EventLoop()
}
if(Transmitter.music_shutdown) {
#if HAS_EXTENDED_AUDIO
if(AUDIO_VoiceAvailable()) {
MUSIC_Play(MUSIC_SHUTDOWN);
while (CLOCK_getms() < audio_queue_time) {
// Wait for voice to finished
CLOCK_ResetWatchdog();
}
} else {
#else
{
// We wait ~1sec for shutdown buzzer music finished
unsigned int time;
MUSIC_Play(MUSIC_SHUTDOWN);
Expand All @@ -250,8 +247,6 @@ void EventLoop()
}
#endif
}
}

PWR_Shutdown();
}
#endif
Expand Down
Loading