diff --git a/Makefile.defconfig.inc b/Makefile.defconfig.inc index fbc8860..08325d4 100644 --- a/Makefile.defconfig.inc +++ b/Makefile.defconfig.inc @@ -1,7 +1,9 @@ SRCTOPDIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -# If you don't want to use libmbe then set DECODEVOICE to zero in Makefile.config.inc -DECODEVOICE := 1 +# If you don't want to use libmbe then set AMBEDECODEVOICE to 0 in Makefile.config.inc +AMBEDECODEVOICE := 1 +# If you don't want to use libmp3lame then set MP3ENCODEVOICE to 0 in Makefile.config.inc +MP3ENCODEVOICE := 1 # If Makefile.config.inc exists, we include it. ifeq ($(wildcard $(SRCTOPDIR)/Makefile.config.inc),$(SRCTOPDIR)/Makefile.config.inc) diff --git a/README.md b/README.md index 346bb99..a7ecd53 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ You'll need to have the following libs installed on your system to compile dmrsh - libsnmp-dev / net-snmp-devel - libmysqlclient-dev / mariadb-devel - [mbelib](https://github.com/szechyjs/mbelib) (optional) +- libmp3lame-dev (optional) Instructions on compiling and installing: @@ -45,7 +46,15 @@ Now you will have dmrshark installed to **/opt/dmrshark**. If you don't want to use libmbe, create **Makefile.config.inc** in the dmrshark source root directory, and add the following: ``` -DECODEVOICE := 0 +AMBEDECODEVOICE := 0 +``` + +### libmp3lame + +If you don't want to use libmp3lame, create **Makefile.config.inc** in the dmrshark source root directory, and add the following: + +``` +MP3ENCODEVOICE := 0 ``` ## Configuration @@ -97,6 +106,7 @@ repeaterhosts=1.2.3.4,repeater123.nonoo.hu savefiledir= savetorawfile=1 savedecodedtorawfile=1 +savedecodedtomp3file=1 timeslot=1 decodequality=3 @@ -106,6 +116,7 @@ repeaterhosts=* savefiledir= savetorawfile=1 savedecodedtorawfile=1 +savedecodedtomp3file=1 timeslot=2 decodequality=64 ``` @@ -119,6 +130,7 @@ Voice stream configure variables: - **savefiledir**: Captured voice files will be saved to this directory. If empty, files will be saved to the current directory. - **savetorawfile**: Set this to 1 if you want to save raw AMBE2+ voice data. - **savedecodedtorawfile**: Set this to 1 if you want to save raw, but decoded voice data. Samples are saved as 8kHz IEEE 32bit floats. +- **savedecodedtomp3file**: Set this to 1 if you want to save decoded voice data in MP3 files. - **decodequality**: Quality of AMBE2+ decoding, valid values are between 1 and 64, 1 is the worst and 64 is the best quality. Default value is 3. Note that increasing decoding quality increases used CPU time. ## Running diff --git a/build/dmrshark/Makefile.goals b/build/dmrshark/Makefile.goals index 43f4428..eab676c 100644 --- a/build/dmrshark/Makefile.goals +++ b/build/dmrshark/Makefile.goals @@ -6,9 +6,12 @@ include ../../make/Makefile.target.inc LIBS := $(LIBS) base config daemon comm remotedb dmrpacket coding voicestreams PREBUILTLIBS := pcap snmp mysqlclient pthread -ifeq ($(DECODEVOICE),1) +ifeq ($(AMBEDECODEVOICE),1) PREBUILTLIBS := $(PREBUILTLIBS) mbe endif +ifeq ($(MP3ENCODEVOICE),1) +PREBUILTLIBS := $(PREBUILTLIBS) mp3lame +endif include ../../make/Makefile.build.inc include ../../make/Makefile.common.inc diff --git a/libs/comm/ipsc.c b/libs/comm/ipsc.c index ae8fbf4..d920f08 100644 --- a/libs/comm/ipsc.c +++ b/libs/comm/ipsc.c @@ -98,7 +98,7 @@ void ipsc_processpacket(struct ip *ip_packet, uint16_t length) { // host of the DMR master, and IP packets are just routed through. if (repeater != NULL || (repeater = repeaters_findbyip(&ip_packet->ip_src)) != NULL) { console_log(LOGLEVEL_IPSC "ipsc [%s", repeaters_get_display_string_for_ip(&ip_packet->ip_src)); - console_log(LOGLEVEL_IPSC "->%s]: decoded dmr ts %u slot type: %s (0x%.4x) call type: %s (0x%.2x) dstid %u srcid %u\n", + console_log(LOGLEVEL_IPSC "->%s]: dmr packet ts %u slot type: %s (0x%.4x) call type: %s (0x%.2x) dstid %u srcid %u\n", repeaters_get_display_string_for_ip(&ip_packet->ip_dst), ipsc_packet.timeslot, ipscpacket_get_readable_slot_type(ipsc_packet.slot_type), ipsc_packet.slot_type, diff --git a/libs/config/config-voicestreams.c b/libs/config/config-voicestreams.c index 4085b7b..1c756ea 100644 --- a/libs/config/config-voicestreams.c +++ b/libs/config/config-voicestreams.c @@ -187,6 +187,54 @@ int config_voicestreams_get_savedecodedtorawfile(char *streamname) { return value; } +int config_voicestreams_get_savedecodedtomp3file(char *streamname) { + GError *error = NULL; + int value = 0; + char *key = "savedecodedtomp3file"; + int defaultvalue = 0; + + pthread_mutex_lock(config_get_mutex()); + value = g_key_file_get_integer(config_get_keyfile(), streamname, key, &error); + if (error) { + value = defaultvalue; + g_key_file_set_integer(config_get_keyfile(), streamname, key, value); + } + pthread_mutex_unlock(config_get_mutex()); + return value; +} + +int config_voicestreams_get_mp3bitrate(char *streamname) { + GError *error = NULL; + int value = 0; + char *key = "mp3bitrate"; + int defaultvalue = 32; + + pthread_mutex_lock(config_get_mutex()); + value = g_key_file_get_integer(config_get_keyfile(), streamname, key, &error); + if (error) { + value = defaultvalue; + g_key_file_set_integer(config_get_keyfile(), streamname, key, value); + } + pthread_mutex_unlock(config_get_mutex()); + return value; +} + +int config_voicestreams_get_mp3quality(char *streamname) { + GError *error = NULL; + int value = 0; + char *key = "mp3quality"; + int defaultvalue = 0; + + pthread_mutex_lock(config_get_mutex()); + value = g_key_file_get_integer(config_get_keyfile(), streamname, key, &error); + if (error) { + value = defaultvalue; + g_key_file_set_integer(config_get_keyfile(), streamname, key, value); + } + pthread_mutex_unlock(config_get_mutex()); + return value; +} + int config_voicestreams_get_timeslot(char *streamname) { GError *error = NULL; int value = 0; @@ -238,6 +286,13 @@ void config_voicestreams_init(void) { free(tmp); config_voicestreams_get_savetorawfile(voicestreams[i]); config_voicestreams_get_savedecodedtorawfile(voicestreams[i]); + config_voicestreams_get_savedecodedtomp3file(voicestreams[i]); +#ifndef MP3ENCODEVOICE + if (config_voicestreams_get_savedecodedtomp3file(voicestreams[i])) + console_log("config warning: voice stream %s has mp3 encoding enabled, but mp3 encoding is not compiled in\n", voicestreams[i]); +#endif + config_voicestreams_get_mp3bitrate(voicestreams[i]); + config_voicestreams_get_mp3quality(voicestreams[i]); config_voicestreams_get_timeslot(voicestreams[i]); config_voicestreams_get_decodequality(voicestreams[i]); @@ -248,7 +303,7 @@ void config_voicestreams_init(void) { } console_log("config: loaded %u voice stream configs\n", i); -#ifndef DECODEVOICE +#ifndef AMBEDECODEVOICE if (i > 0) console_log("config warning: voice streams defined in config but voice decoding is not compiled in\n"); #endif diff --git a/libs/config/config-voicestreams.h b/libs/config/config-voicestreams.h index c06ee77..a32b1a1 100644 --- a/libs/config/config-voicestreams.h +++ b/libs/config/config-voicestreams.h @@ -28,6 +28,9 @@ char *config_voicestreams_get_repeaterhosts(char *streamname); char *config_voicestreams_get_savefiledir(char *streamname); int config_voicestreams_get_savetorawfile(char *streamname); int config_voicestreams_get_savedecodedtorawfile(char *streamname); +int config_voicestreams_get_savedecodedtomp3file(char *streamname); +int config_voicestreams_get_mp3bitrate(char *streamname); +int config_voicestreams_get_mp3quality(char *streamname); int config_voicestreams_get_timeslot(char *streamname); int config_voicestreams_get_decodequality(char *streamname); diff --git a/libs/daemon/console.c b/libs/daemon/console.c index dc41dcf..1eb4fad 100644 --- a/libs/daemon/console.c +++ b/libs/daemon/console.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -216,12 +215,27 @@ static flag_t console_isloglevelchar(char loglevel_char) { } } -static void console_log_display(char *text, va_list *argptr) { +static int8_t console_loglevel_match(const char *format) { + uint8_t first_non_format_char_pos; + uint8_t i; + + first_non_format_char_pos = 0; + while (console_isloglevelchar(format[first_non_format_char_pos])) + first_non_format_char_pos++; + + for (i = 0; i < first_non_format_char_pos; i++) { + if (!console_isallowedtodisplay(format[i])) + return -1; + } + return first_non_format_char_pos; +} + +static void console_log_display(const char *text, va_list argptr) { char buffer[CONSOLELOGBUFFERSIZE]; size_t buffer_length = 0; pthread_mutex_lock(&console_mutex); - vsnprintf(buffer, sizeof(buffer), text, *argptr); + vsnprintf(buffer, sizeof(buffer), text, argptr); buffer_length = strlen(buffer); printf("%s", buffer); @@ -232,26 +246,30 @@ static void console_log_display(char *text, va_list *argptr) { pthread_mutex_unlock(&console_mutex); } -void console_log(char *format, ...) { +void console_log(const char *format, ...) { va_list argptr; - uint8_t first_non_format_char_pos; - uint8_t i; + int8_t first_non_format_char_pos; va_start(argptr, format); - first_non_format_char_pos = 0; - while (console_isloglevelchar(format[first_non_format_char_pos])) - first_non_format_char_pos++; + first_non_format_char_pos = console_loglevel_match(format); + if (first_non_format_char_pos < 0) + return; - for (i = 0; i < first_non_format_char_pos; i++) { - if (!console_isallowedtodisplay(format[i])) - return; - } - console_log_display(format+first_non_format_char_pos, &argptr); + console_log_display(format+first_non_format_char_pos, argptr); va_end(argptr); } +void console_log_va_list(const char *loglevel, const char *format, va_list argptr) { + int8_t first_non_format_char_pos = console_loglevel_match(loglevel); + + if (first_non_format_char_pos < 0) + return; + + console_log_display(format, argptr); +} + void console_process(void) { int r, i; char buf[CONSOLE_INPUTBUFFERSIZE]; diff --git a/libs/daemon/console.h b/libs/daemon/console.h index aba0b12..90651ba 100644 --- a/libs/daemon/console.h +++ b/libs/daemon/console.h @@ -20,6 +20,8 @@ #include +#include + #define LOGLEVEL_DEBUG "\x01" #define LOGLEVEL_DEBUG_VAL 0x01 #define LOGLEVEL_IPSC "\x02" @@ -70,7 +72,8 @@ uint16_t console_get_bufferpos(void); void console_rxbuf_add(char inputchar, flag_t vt100supported); void console_addtologfile(char *msg, int msglen); -void console_log(char *format, ...); +void console_log(const char *format, ...); +void console_log_va_list(const char *loglevel, const char *format, va_list argptr); void console_process(void); void console_init(void); diff --git a/libs/voicestreams/voicestreams-decode.c b/libs/voicestreams/voicestreams-decode.c index c88dc4b..a1bccc3 100644 --- a/libs/voicestreams/voicestreams-decode.c +++ b/libs/voicestreams/voicestreams-decode.c @@ -21,7 +21,7 @@ #include -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE static uint8_t voicestreams_decode_deinterleave_matrix_w[36] = { 0, 1, 0, 1, 0, 1, @@ -94,4 +94,4 @@ voicestreams_decoded_frame_t *voicestreams_decode_ambe_frame(dmrpacket_payload_a return &decoded_frame; } -#endif /* ifdef DECODEVOICE */ +#endif /* ifdef AMBEDECODEVOICE */ diff --git a/libs/voicestreams/voicestreams-mp3.c b/libs/voicestreams/voicestreams-mp3.c new file mode 100644 index 0000000..3273aae --- /dev/null +++ b/libs/voicestreams/voicestreams-mp3.c @@ -0,0 +1,122 @@ +/* + * This file is part of dmrshark. + * + * dmrshark is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dmrshark is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dmrshark. If not, see . +**/ + +#include + +#if defined(AMBEDECODEVOICE) && defined(MP3ENCODEVOICE) + +#include "voicestreams-mp3.h" + +#include + +#include + +static void voicestreams_mp3_handleerror(int resultcode) { + switch (resultcode) { + case -1: console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3 error: encode failed with mp3buf was too small\n"); break; + case -2: console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3 error: encode failed with malloc problem\n"); break; + case -3: console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3 error: encode failed with lame_init_params() not called\n"); break; + case -4: console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3 error: encode failed with psycho acoustic problems\n"); break; + } +} + +// If the function is called with decoded_frame == NULL, then it only empties out the remaining buffer. +voicestreams_mp3_frame_t *voicestreams_mp3_encode(voicestream_t *voicestream, voicestreams_decoded_frame_t *decoded_frame) { + static voicestreams_mp3_frame_t mp3frame; + int res; + + if (decoded_frame) { + if (voicestream->mp3_buf_pos < sizeof(voicestream->mp3_buf)/sizeof(voicestream->mp3_buf[0])) { + memcpy(voicestream->mp3_buf+voicestream->mp3_buf_pos, decoded_frame->samples, VOICESTREAMS_DECODED_AMBE_FRAME_SAMPLES_COUNT*sizeof(decoded_frame->samples[0])); + voicestream->mp3_buf_pos += VOICESTREAMS_DECODED_AMBE_FRAME_SAMPLES_COUNT; + } + } + + if (voicestream->mp3_buf_pos >= sizeof(voicestream->mp3_buf)/sizeof(voicestream->mp3_buf[0]) || decoded_frame == NULL) { + res = lame_encode_buffer_ieee_float(voicestream->mp3_flags, voicestream->mp3_buf, voicestream->mp3_buf, voicestream->mp3_buf_pos, mp3frame.bytes, sizeof(mp3frame.bytes)); + voicestream->mp3_buf_pos = 0; + if (res < 0) { + mp3frame.bytes_size = 0; + voicestreams_mp3_handleerror(res); + return NULL; + } + mp3frame.bytes_size = res; + return &mp3frame; + } + return NULL; +} + +void voicestreams_mp3_encode_flush(voicestream_t *voicestream, voicestreams_mp3_frame_t *mp3frame) { + int res; + + if (mp3frame == NULL) + return; + + res = lame_encode_flush(voicestream->mp3_flags, mp3frame->bytes, mp3frame->bytes_size); + if (res < 0) { + voicestreams_mp3_handleerror(res); + return; + } + lame_mp3_tags_fid(voicestream->mp3_flags, NULL); +} + +void voicestreams_mp3_resetbuf(voicestream_t *voicestream) { + voicestream->mp3_buf_pos = 0; +} + +static void voicestreams_mp3_lamelog(const char *format, va_list ap) { + console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3: lame says: "); + console_log_va_list(LOGLEVEL_VOICESTREAMS, format, ap); +} + +static void voicestreams_mp3_lamelog_err(const char *format, va_list ap) { + console_log(LOGLEVEL_VOICESTREAMS "voicestreams-mp3 error: lame says: "); + console_log_va_list(LOGLEVEL_VOICESTREAMS, format, ap); +} + +void voicestreams_mp3_init(voicestream_t *voicestream) { + voicestream->mp3_buf_pos = 0; + + voicestream->mp3_flags = lame_init(); + + lame_set_errorf(voicestream->mp3_flags, voicestreams_mp3_lamelog_err); + lame_set_debugf(voicestream->mp3_flags, voicestreams_mp3_lamelog); + lame_set_msgf(voicestream->mp3_flags, voicestreams_mp3_lamelog); + + lame_set_num_channels(voicestream->mp3_flags, 1); + lame_set_in_samplerate(voicestream->mp3_flags, 8000); + lame_set_brate(voicestream->mp3_flags, voicestream->mp3bitrate); + lame_set_mode(voicestream->mp3_flags, MONO); + lame_set_quality(voicestream->mp3_flags, voicestream->mp3quality); + lame_set_bWriteVbrTag(voicestream->mp3_flags, 0); + + if (lame_init_params(voicestream->mp3_flags) < 0) { + lame_close(voicestream->mp3_flags); + voicestream->mp3_flags = NULL; + console_log("voicestreams-mp3 error: failed to initialize libmp3lame\n"); + } else + console_log("voicestreams-mp3: initialized libmp3lame encoder\n"); +} + +void voicestreams_mp3_deinit(voicestream_t *voicestream) { + if (voicestream->mp3_flags) { + lame_close(voicestream->mp3_flags); + voicestream->mp3_flags = NULL; + } +} + +#endif /* if defined(AMBEDECODEVOICE) && defined(MP3ENCODEVOICE) */ diff --git a/libs/voicestreams/voicestreams-mp3.h b/libs/voicestreams/voicestreams-mp3.h new file mode 100644 index 0000000..caad497 --- /dev/null +++ b/libs/voicestreams/voicestreams-mp3.h @@ -0,0 +1,35 @@ +/* + * This file is part of dmrshark. + * + * dmrshark is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dmrshark is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dmrshark. If not, see . +**/ + +#ifndef VOICESTREAMS_MP3_H_ +#define VOICESTREAMS_MP3_H_ + +#include "voicestreams-decode.h" + +typedef struct { + uint8_t bytes[17200]; // 8000 samples per sec., 1.25*8000 + 7200 + uint16_t bytes_size; +} voicestreams_mp3_frame_t; + +voicestreams_mp3_frame_t *voicestreams_mp3_encode(voicestream_t *voicestream, voicestreams_decoded_frame_t *decoded_frame); +void voicestreams_mp3_encode_flush(voicestream_t *voicestream, voicestreams_mp3_frame_t *mp3frame); +void voicestreams_mp3_resetbuf(voicestream_t *voicestream); + +void voicestreams_mp3_init(voicestream_t *voicestream); +void voicestreams_mp3_deinit(voicestream_t *voicestream); + +#endif diff --git a/libs/voicestreams/voicestreams-process.c b/libs/voicestreams/voicestreams-process.c index e209dfd..fefaea8 100644 --- a/libs/voicestreams/voicestreams-process.c +++ b/libs/voicestreams/voicestreams-process.c @@ -20,6 +20,7 @@ #include "voicestreams.h" #include "voicestreams-process.h" #include "voicestreams-decode.h" +#include "voicestreams-mp3.h" #include #include @@ -107,6 +108,34 @@ static void voicestreams_process_apply_gain(voicestreams_decoded_frame_t *decode } } +static void voicestreams_process_mp3(voicestream_t *voicestream, voicestreams_decoded_frame_t *decoded_frame) { + FILE *f; + char *fn; + size_t saved_items; + voicestreams_mp3_frame_t *mp3frame; + + if (voicestream == NULL) // Calling the function with decoded_frame == NULL is allowed. + return; + + if (voicestream->savedecodedtomp3file) { + mp3frame = voicestreams_mp3_encode(voicestream, decoded_frame); + if (mp3frame != NULL) { + if (decoded_frame == NULL) + voicestreams_mp3_encode_flush(voicestream, mp3frame); // This closes the call's mp3 segment. + + fn = voicestreams_get_stream_filename(voicestream, ".mp3"); + f = fopen(fn, "a"); + if (!f) { + console_log(LOGLEVEL_VOICESTREAMS LOGLEVEL_DEBUG "voicestreams [%s] error: can't save mp3 frame to %s\n", voicestream->name, fn); + return; + } + saved_items = fwrite(mp3frame->bytes, 1, mp3frame->bytes_size, f); + fclose(f); + console_log(LOGLEVEL_VOICESTREAMS LOGLEVEL_DEBUG "voicestreams [%s]: saved %u mp3 frame bytes to %s\n", voicestream->name, saved_items, fn); + } + } +} + static void voicestreams_process_decoded_frame(voicestream_t *voicestream, voicestreams_decoded_frame_t *decoded_frame) { FILE *f; char *fn; @@ -129,6 +158,8 @@ static void voicestreams_process_decoded_frame(voicestream_t *voicestream, voice fclose(f); console_log(LOGLEVEL_VOICESTREAMS LOGLEVEL_DEBUG "voicestreams [%s]: saved %u decoded voice packet bytes to %s\n", voicestream->name, saved_items*sizeof(decoded_frame->samples[0]), fn); } + + voicestreams_process_mp3(voicestream, decoded_frame); } void voicestreams_processpacket(ipscpacket_t *ipscpacket, repeater_t *repeater) { @@ -136,7 +167,7 @@ void voicestreams_processpacket(ipscpacket_t *ipscpacket, repeater_t *repeater) dmrpacket_payload_voice_bits_t *voice_bits; uint8_t i; uint8_t voice_bytes[sizeof(dmrpacket_payload_voice_bits_t)/8]; -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE voicestreams_decoded_frame_t *decoded_frame; #endif @@ -174,7 +205,7 @@ void voicestreams_processpacket(ipscpacket_t *ipscpacket, repeater_t *repeater) if (voicestream->savetorawfile) voicestreams_process_savetorawfile(voice_bytes, sizeof(voice_bytes), voicestream); -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE console_log(LOGLEVEL_VOICESTREAMS LOGLEVEL_DEBUG "voicestreams [%s]: decoding frame 0\n", voicestream->name); decoded_frame = voicestreams_decode_ambe_frame(&voice_bits->ambe_frames.frames[0], voicestream); voicestreams_process_decoded_frame(voicestream, decoded_frame); @@ -199,13 +230,22 @@ void voicestreams_process_call_start(voicestream_t *voicestream, repeater_t *rep voicestream->currently_streaming_repeater = (struct repeater_t *)repeater; voicestream->rms_vol = voicestream->avg_rms_vol = voicestream->rms_vol_buf_pos = 0; + voicestreams_mp3_resetbuf(voicestream); } void voicestreams_process_call_end(voicestream_t *voicestream, repeater_t *repeater) { + uint8_t i; + voicestreams_decoded_frame_t zero_frame = { .samples = { 0, } }; + if (!voicestream || !voicestream->enabled) return; voicestreams_process_rms_vol_calc(voicestream); console_log(LOGLEVEL_VOICESTREAMS "voicestreams [%s]: call end on repeater %s\n", voicestream->name, repeaters_get_display_string(repeater)); voicestream->currently_streaming_repeater = NULL; + + // Flushing out the buffer. + for (i = 0; i < 10; i++) + voicestreams_process_mp3(voicestream, &zero_frame); + voicestreams_process_mp3(voicestream, NULL); } diff --git a/libs/voicestreams/voicestreams.c b/libs/voicestreams/voicestreams.c index 1994b5b..b9d36a8 100644 --- a/libs/voicestreams/voicestreams.c +++ b/libs/voicestreams/voicestreams.c @@ -19,6 +19,7 @@ #include "voicestreams.h" #include "voicestreams-process.h" +#include "voicestreams-mp3.h" #include #include @@ -117,7 +118,7 @@ void voicestreams_init(void) { char **streamnames = config_voicestreams_get_streamnames(); char **streamnames_i = streamnames; voicestream_t *new_vs; -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE char mbeversion[25]; #endif @@ -146,11 +147,17 @@ void voicestreams_init(void) { new_vs->savefiledir = config_voicestreams_get_savefiledir(new_vs->name); new_vs->savetorawfile = config_voicestreams_get_savetorawfile(new_vs->name); new_vs->savedecodedtorawfile = config_voicestreams_get_savedecodedtorawfile(new_vs->name); + new_vs->savedecodedtomp3file = config_voicestreams_get_savedecodedtomp3file(new_vs->name); + new_vs->mp3bitrate = config_voicestreams_get_mp3bitrate(new_vs->name); + new_vs->mp3quality = config_voicestreams_get_mp3quality(new_vs->name); new_vs->timeslot = config_voicestreams_get_timeslot(new_vs->name); new_vs->decodequality = config_voicestreams_get_decodequality(new_vs->name); -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE mbe_initMbeParms(&new_vs->cur_mp, &new_vs->prev_mp, &new_vs->prev_mp_enhanced); +#ifdef MP3ENCODEVOICE + voicestreams_mp3_init(new_vs); +#endif #endif new_vs->next = voicestreams; @@ -162,24 +169,28 @@ void voicestreams_init(void) { } config_voicestreams_free_streamnames(streamnames); -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE mbe_printVersion(mbeversion); console_log("voicestreams: using mbelib v%s for voice decoding\n", mbeversion); #endif } void voicestreams_deinit(void) { - voicestream_t *vs; + voicestream_t *next_vs; console_log("voicestreams: deinit\n"); while (voicestreams != NULL) { +#ifdef MP3ENCODEVOICE + voicestreams_mp3_deinit(voicestreams); +#endif + free(voicestreams->name); free(voicestreams->repeaterhosts); free(voicestreams->savefiledir); - vs = voicestreams->next; + next_vs = voicestreams->next; free(voicestreams); - voicestreams = vs; + voicestreams = next_vs; } } diff --git a/libs/voicestreams/voicestreams.h b/libs/voicestreams/voicestreams.h index a2c9a4f..264f8a1 100644 --- a/libs/voicestreams/voicestreams.h +++ b/libs/voicestreams/voicestreams.h @@ -21,8 +21,11 @@ #include #include -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE #include +#ifdef MP3ENCODEVOICE +#include +#endif #endif #define VOICESTREAMS_DECODED_AMBE_FRAME_SAMPLES_COUNT 160 @@ -34,6 +37,9 @@ typedef struct voicestream_st { char *savefiledir; flag_t savetorawfile; flag_t savedecodedtorawfile; + flag_t savedecodedtomp3file; + uint8_t mp3bitrate; + uint8_t mp3quality; flag_t timeslot; uint8_t decodequality; @@ -42,10 +48,16 @@ typedef struct voicestream_st { int8_t rms_vol; int8_t avg_rms_vol; -#ifdef DECODEVOICE +#ifdef AMBEDECODEVOICE mbe_parms cur_mp; mbe_parms prev_mp; mbe_parms prev_mp_enhanced; + +#ifdef MP3ENCODEVOICE + lame_global_flags *mp3_flags; + float mp3_buf[160]; + uint16_t mp3_buf_pos; +#endif #endif struct repeater_t *currently_streaming_repeater; diff --git a/make/Makefile.target.inc b/make/Makefile.target.inc index e6e1a80..878d183 100644 --- a/make/Makefile.target.inc +++ b/make/Makefile.target.inc @@ -14,8 +14,11 @@ CFLAGS := $(CFLAGS) -g -Wall -std=gnu99 -O4 -DGITHASH=\"$(GITHASH)\" \ $(shell pkg-config --cflags glib-2.0) \ -DARCH_X86 -funsigned-bitfields -funsigned-char -Wno-unused-result -ifeq ($(DECODEVOICE), 1) -CFLAGS := $(CFLAGS) -DDECODEVOICE +ifeq ($(AMBEDECODEVOICE), 1) +CFLAGS := $(CFLAGS) -DAMBEDECODEVOICE +endif +ifeq ($(MP3ENCODEVOICE), 1) +CFLAGS := $(CFLAGS) -DMP3ENCODEVOICE endif LDAFTER := $(LDAFTER) $(shell pkg-config --libs glib-2.0)