Initial Commit
Downloaded from http://www.aishub.net/downloads/aisdecoder-1.0.0.tar.gz
This commit is contained in:
commit
a6f6209826
|
@ -0,0 +1,105 @@
|
|||
project(aisdecoder)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
|
||||
set(STATIC_LIB "${PROJECT_NAME}_static_lib")
|
||||
set(DYNAMIC_LIB "${PROJECT_NAME}_dynamic_lib")
|
||||
|
||||
macro(get_WIN32_WINNT version)
|
||||
if (WIN32 AND CMAKE_SYSTEM_VERSION)
|
||||
set(ver ${CMAKE_SYSTEM_VERSION})
|
||||
string(REPLACE "." "" ver ${ver})
|
||||
string(REGEX REPLACE "([0-9])" "0\\1" ver ${ver})
|
||||
set(${version} "0x${ver}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if(NOT WIN32)
|
||||
CHECK_INCLUDE_FILES(alsa/asoundlib.h HAVE_ALSA)
|
||||
CHECK_INCLUDE_FILES(pulse/pulseaudio.h HAVE_PULSEAUDIO)
|
||||
else()
|
||||
get_WIN32_WINNT(ver)
|
||||
if(${CMAKE_SYSTEM_VERSION} LESS 5.1)
|
||||
MESSAGE(FATAL_ERROR "Windows XP or higher is required")
|
||||
endif()
|
||||
add_definitions(-D_WIN32_WINNT=${ver})
|
||||
endif()
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
if(NOT $ENV{CMAKE_BUILD_TYPE} STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE $ENV{CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
|
||||
MESSAGE(STATUS "Build configuration: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g -Wall")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall")
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} STREQUAL "RELEASE")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-s")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
if(NOT HAVE_ALSA AND NOT HAVE_PULSEAUDIO)
|
||||
MESSAGE(FATAL_ERROR "The development files for ALSA or PulseAudio are required - libasound-dev, libpulse-dev")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/lib)
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
|
||||
set(SRC_LIST_LIB "${CMAKE_CURRENT_SOURCE_DIR}/src/sounddecoder.c")
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/lib SRC_LIST_LIB)
|
||||
|
||||
if(NOT WIN32)
|
||||
if(HAVE_PULSEAUDIO)
|
||||
aux_source_directory(src/lib/pulseaudio SRC_LIST_LIB)
|
||||
set(L_PULSE pulse-simple)
|
||||
else()
|
||||
message(WARNING "You do not have the development files for pulseaudio (DISABLE).")
|
||||
endif()
|
||||
|
||||
if(HAVE_ALSA)
|
||||
aux_source_directory(src/lib/alsaaudio SRC_LIST_LIB)
|
||||
set(L_ALSA asound)
|
||||
else()
|
||||
message(WARNING "You do not have the development files for ASLA (DISABLE).")
|
||||
endif()
|
||||
else()
|
||||
aux_source_directory(src/lib/winmmaudio SRC_LIST_LIB)
|
||||
endif()
|
||||
|
||||
add_library(${DYNAMIC_LIB} SHARED ${SRC_LIST_LIB})
|
||||
set_target_properties(${DYNAMIC_LIB} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
|
||||
|
||||
add_library(${STATIC_LIB} STATIC ${SRC_LIST_LIB})
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${DYNAMIC_LIB} winmm)
|
||||
else()
|
||||
set(MYLIB_VERSION_MAJOR 1)
|
||||
set(MYLIB_VERSION_MINOR 0)
|
||||
set(MYLIB_VERSION_PATCH 0)
|
||||
set(MYLIB_VERSION_STRING ${MYLIB_VERSION_MAJOR}.${MYLIB_VERSION_MINOR}.${MYLIB_VERSION_PATCH})
|
||||
set_target_properties(${DYNAMIC_LIB}
|
||||
PROPERTIES
|
||||
VERSION ${MYLIB_VERSION_STRING}
|
||||
SOVERSION ${MYLIB_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||
target_link_libraries(${PROJECT_NAME} ${STATIC_LIB})
|
||||
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(${PROJECT_NAME} ${L_ALSA} ${L_PULSE})
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} winmm ws2_32)
|
||||
endif()
|
|
@ -0,0 +1,3 @@
|
|||
#cmakedefine PROJECT_NAME "${PROJECT_NAME}"
|
||||
#cmakedefine HAVE_ALSA
|
||||
#cmakedefine HAVE_PULSEAUDIO
|
|
@ -0,0 +1,119 @@
|
|||
|
||||
/*
|
||||
* input.c
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "alsaaudio.h"
|
||||
#include "hmalloc.h"
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
int input_initialize(snd_pcm_t * handle, short **buffer, int *buffer_l, int channels_num, char *error_msg)
|
||||
{
|
||||
int err;
|
||||
int dir;
|
||||
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
|
||||
sprintf(error_msg, "Error initializing hwparams");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
sprintf(error_msg, "Error setting acecss mode (SND_PCM_ACCESS_RW_INTERLEAVED): %s", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {
|
||||
sprintf(error_msg, "Error setting format (SND_PCM_FORMAT_S16_LE): %s", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_channels(handle, hwparams, channels_num)) < 0) {
|
||||
sprintf(error_msg, "Error setting channels %d: %s", channels_num, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int rate = 48000;
|
||||
if ((err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0)) < 0) {
|
||||
sprintf(error_msg, "Error setting sample rate (%d): %s", rate, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t size = 4096; /* number of frames */
|
||||
|
||||
dir = 0;
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &size, &dir)) < 0) {
|
||||
sprintf(error_msg, "Error setting buffer size (%lu): %s", size, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params(handle, hwparams)) < 0) {
|
||||
sprintf(error_msg, "Error writing hwparams: %s", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_get_period_size(hwparams, &size, &dir);
|
||||
//int extra = (int) size % 5;
|
||||
//*buffer_l = (int) size - extra;
|
||||
*buffer_l = (int) size;
|
||||
int buffer_len_in_bytes = *buffer_l * sizeof(short) * channels_num;
|
||||
|
||||
// hlog(LOG_DEBUG, LOGPREFIX "Using sound buffer size: %d frames of %d channels: %d bytes",
|
||||
// *buffer_l, channels, buffer_len_in_bytes);
|
||||
|
||||
*buffer = (short *) hmalloc(buffer_len_in_bytes);
|
||||
bzero(*buffer, buffer_len_in_bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int alsa_read(snd_pcm_t * handle, short *buffer, int count)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snd_pcm_readi(handle, buffer, count);
|
||||
|
||||
if (err == -EPIPE) {
|
||||
// hlog(LOG_ERR, LOGPREFIX "Overrun");
|
||||
snd_pcm_prepare(handle);
|
||||
} else if (err < 0) {
|
||||
// hlog(LOG_ERR, LOGPREFIX "Read error");
|
||||
} else if (err != count) {
|
||||
// hlog(LOG_INFO, LOGPREFIX "Short read, read %d frames", err);
|
||||
} else {
|
||||
/*hlog(LOG_DEBUG, LOGPREFIX "Read %d samples", err); */
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void input_cleanup(snd_pcm_t *handle)
|
||||
{
|
||||
snd_pcm_close(handle);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
/*
|
||||
* input.h
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INC_INPUT_H
|
||||
#define INC_INPUT_H
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int input_initialize(snd_pcm_t * handle, short **, int *, int channels_num, char *error_msg);
|
||||
int alsa_read(snd_pcm_t * handle, short *buffer, int count);
|
||||
void input_cleanup(snd_pcm_t *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef CALLBACKS_H
|
||||
#define CALLBACKS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*receiver_on_level_changed)(float level, int channel, unsigned char high);
|
||||
typedef void (*decoder_on_nmea_sentence_received)(const char *sentence,
|
||||
unsigned int length,
|
||||
unsigned char sentences,
|
||||
unsigned char sentencenum);
|
||||
|
||||
extern receiver_on_level_changed on_sound_level_changed;
|
||||
extern decoder_on_nmea_sentence_received on_nmea_sentence_received;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // CALLBACKS_H
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* filter-i386.h -- optimized filter routines
|
||||
*
|
||||
* Copyright (C) 1996
|
||||
* Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifndef _FILTER_I386_H
|
||||
#define _FILTER_I386_H
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#define __HAVE_ARCH_MAC
|
||||
#define mac(a,b,size) \
|
||||
(__builtin_constant_p(size) ? __mac_c((a),(b),(size)) : __mac_g((a),(b),(size)))
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern inline float __mac_g(const float *a, const float *b,
|
||||
unsigned int size)
|
||||
{
|
||||
float sum = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
sum += (*a++) * (*b++);
|
||||
return sum;
|
||||
}
|
||||
|
||||
extern inline float __mac_c(const float *a, const float *b,
|
||||
unsigned int size)
|
||||
{
|
||||
float f;
|
||||
|
||||
/*
|
||||
* inspired from Phil Karn, KA9Q's home page
|
||||
*/
|
||||
switch (size) {
|
||||
case 53:
|
||||
asm volatile ("flds (%1);\n\t"
|
||||
"fmuls (%2);\n\t"
|
||||
"flds 4(%1);\n\t"
|
||||
"fmuls 4(%2);\n\t"
|
||||
"flds 8(%1);\n\t"
|
||||
"fmuls 8(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 12(%1);\n\t"
|
||||
"fmuls 12(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 16(%1);\n\t"
|
||||
"fmuls 16(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 20(%1);\n\t"
|
||||
"fmuls 20(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 24(%1);\n\t"
|
||||
"fmuls 24(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 28(%1);\n\t"
|
||||
"fmuls 28(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 32(%1);\n\t"
|
||||
"fmuls 32(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 36(%1);\n\t"
|
||||
"fmuls 36(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 40(%1);\n\t"
|
||||
"fmuls 40(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 44(%1);\n\t"
|
||||
"fmuls 44(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 48(%1);\n\t"
|
||||
"fmuls 48(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 52(%1);\n\t"
|
||||
"fmuls 52(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 56(%1);\n\t"
|
||||
"fmuls 56(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 60(%1);\n\t"
|
||||
"fmuls 60(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 64(%1);\n\t"
|
||||
"fmuls 64(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 68(%1);\n\t"
|
||||
"fmuls 68(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 72(%1);\n\t"
|
||||
"fmuls 72(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 76(%1);\n\t"
|
||||
"fmuls 76(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 80(%1);\n\t"
|
||||
"fmuls 80(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 84(%1);\n\t"
|
||||
"fmuls 84(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 88(%1);\n\t"
|
||||
"fmuls 88(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 92(%1);\n\t"
|
||||
"fmuls 92(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 96(%1);\n\t"
|
||||
"fmuls 96(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 100(%1);\n\t"
|
||||
"fmuls 100(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 104(%1);\n\t"
|
||||
"fmuls 104(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 108(%1);\n\t"
|
||||
"fmuls 108(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 112(%1);\n\t"
|
||||
"fmuls 112(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 116(%1);\n\t"
|
||||
"fmuls 116(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 120(%1);\n\t"
|
||||
"fmuls 120(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 124(%1);\n\t"
|
||||
"fmuls 124(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 128(%1);\n\t"
|
||||
"fmuls 128(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 132(%1);\n\t"
|
||||
"fmuls 132(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 136(%1);\n\t"
|
||||
"fmuls 136(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 140(%1);\n\t"
|
||||
"fmuls 140(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 144(%1);\n\t"
|
||||
"fmuls 144(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 148(%1);\n\t"
|
||||
"fmuls 148(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 152(%1);\n\t"
|
||||
"fmuls 152(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 156(%1);\n\t"
|
||||
"fmuls 156(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 160(%1);\n\t"
|
||||
"fmuls 160(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 164(%1);\n\t"
|
||||
"fmuls 164(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 168(%1);\n\t"
|
||||
"fmuls 168(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 172(%1);\n\t"
|
||||
"fmuls 172(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 176(%1);\n\t"
|
||||
"fmuls 176(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 180(%1);\n\t"
|
||||
"fmuls 180(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 184(%1);\n\t"
|
||||
"fmuls 184(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 188(%1);\n\t"
|
||||
"fmuls 188(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 192(%1);\n\t"
|
||||
"fmuls 192(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 196(%1);\n\t"
|
||||
"fmuls 196(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 200(%1);\n\t"
|
||||
"fmuls 200(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 204(%1);\n\t"
|
||||
"fmuls 204(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"flds 208(%1);\n\t"
|
||||
"fmuls 208(%2);\n\t"
|
||||
"fxch %%st(2);\n\t"
|
||||
"faddp;\n\t"
|
||||
"faddp;\n\t":"=t" (f):"r"(a), "r"(b):"memory");
|
||||
return f;
|
||||
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Warning: optimize __mac_c(..., ..., %d)\n", size);
|
||||
return __mac_g(a, b, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
#endif /* _FILTER_I386_H */
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* filter.c -- FIR filter
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003
|
||||
* Tomi Manninen (oh2bns@sral.fi)
|
||||
*
|
||||
* This file is part of gMFSK.
|
||||
*
|
||||
* gMFSK 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gMFSK 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 gMFSK; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hmalloc.h"
|
||||
#include "filter.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* This gets used when not optimising
|
||||
*/
|
||||
#ifndef __OPTIMIZE__
|
||||
float filter_mac(const float *a, const float *b, int size)
|
||||
{
|
||||
float sum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
sum += a[i] * b[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct filter *filter_init(int len, float *taps)
|
||||
{
|
||||
struct filter *f;
|
||||
|
||||
f = (struct filter *) hmalloc(sizeof(struct filter));
|
||||
memset(f, 0, sizeof(struct filter));
|
||||
|
||||
f->taps = (float *) hmalloc(len * sizeof(float));
|
||||
memcpy(f->taps, taps, len * sizeof(float));
|
||||
|
||||
f->length = len;
|
||||
f->pointer = f->length;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void filter_free(struct filter *f)
|
||||
{
|
||||
if (f) {
|
||||
hfree(f->taps);
|
||||
hfree(f);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void filter_run(struct filter *f, float in, float *out)
|
||||
{
|
||||
float *ptr = f->buffer + f->pointer++;
|
||||
|
||||
*ptr = in;
|
||||
|
||||
// TODO: optimize: pass filter length as constant to enable
|
||||
// using optimized __mac_c and fix the number of rounds there!
|
||||
#ifndef __HAVE_ARCH_MAC
|
||||
*out = filter_mac(ptr - f->length, f->taps, f->length);
|
||||
#else
|
||||
*out = mac(ptr - f->length, f->taps, f->length);
|
||||
#endif
|
||||
//*out = filter_mac(ptr - f->length, f->taps, 53);
|
||||
|
||||
if (f->pointer == BufferLen) {
|
||||
memcpy(f->buffer,
|
||||
f->buffer + BufferLen - f->length,
|
||||
f->length * sizeof(float));
|
||||
f->pointer = f->length;
|
||||
}
|
||||
}
|
||||
|
||||
short filter_run_buf(struct filter *f, short *in, float *out, int step, int len)
|
||||
{
|
||||
int id = 0;
|
||||
int od = 0;
|
||||
short maxval = 0;
|
||||
int pointer = f->pointer;
|
||||
float *buffer = f->buffer;
|
||||
|
||||
while (od < len) {
|
||||
buffer[pointer] = in[id];
|
||||
|
||||
// look for peak volume
|
||||
if (in[id] > maxval)
|
||||
maxval = in[id];
|
||||
|
||||
#ifndef __HAVE_ARCH_MAC
|
||||
out[od] = filter_mac(&buffer[pointer - f->length], f->taps, f->length);
|
||||
#else
|
||||
out[od] = mac(&buffer[pointer - f->length], f->taps, f->length);
|
||||
#endif
|
||||
pointer++;
|
||||
|
||||
/* the buffer is much smaller than the incoming chunks */
|
||||
if (pointer == BufferLen) {
|
||||
memcpy(buffer,
|
||||
buffer + BufferLen - f->length,
|
||||
f->length * sizeof(float));
|
||||
pointer = f->length;
|
||||
}
|
||||
|
||||
id += step;
|
||||
od++;
|
||||
}
|
||||
|
||||
f->pointer = pointer;
|
||||
|
||||
return maxval;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* filter.h -- FIR filter
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004
|
||||
* Tomi Manninen (oh2bns@sral.fi)
|
||||
*
|
||||
* This file is part of gMFSK.
|
||||
*
|
||||
* gMFSK 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* gMFSK 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 gMFSK; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FILTER_H
|
||||
#define _FILTER_H
|
||||
|
||||
#define BufferLen 1024
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
|
||||
#ifdef __i386__
|
||||
#include "filter-i386.h"
|
||||
#endif /* __i386__ */
|
||||
|
||||
|
||||
#ifndef __HAVE_ARCH_MAC
|
||||
static __inline__ float filter_mac(const float *a, const float *b, int size)
|
||||
{
|
||||
float sum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
sum += a[i] * b[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif /* __HAVE_ARCH_MAC */
|
||||
|
||||
#endif /* __OPTIMIZE__ */
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct filter {
|
||||
int length;
|
||||
float *taps;
|
||||
float buffer[BufferLen];
|
||||
int pointer;
|
||||
};
|
||||
|
||||
extern struct filter *filter_init(int len, float *taps);
|
||||
extern void filter_free(struct filter *f);
|
||||
|
||||
extern void filter_run(struct filter *f, float in, float *out);
|
||||
extern short filter_run_buf(struct filter *f, short *in, float *out, int step, int len);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#endif /* _FILTER_H */
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* (c) Heikki Hannikainen, OH7LZB <hessu@hes.iki.fi>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Replacements for malloc, realloc and free, which never fail,
|
||||
* and might keep statistics on memory allocation...
|
||||
*
|
||||
* GPL'ed, by Heikki Hannikainen <hessu@hes.iki.fi>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hmalloc.h"
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
int mem_panic = 0;
|
||||
|
||||
void *hmalloc(size_t size) {
|
||||
void *p;
|
||||
if (!(p = malloc(size))) {
|
||||
if (mem_panic) exit(1);
|
||||
mem_panic = 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *hrealloc(void *ptr, size_t size) {
|
||||
void *p;
|
||||
|
||||
if (!(p = realloc(ptr, size))) {
|
||||
if (mem_panic) exit(1);
|
||||
mem_panic = 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void hfree(void *ptr) {
|
||||
if (ptr) free(ptr);
|
||||
}
|
||||
|
||||
char *hstrdup(const char *s) {
|
||||
char *p;
|
||||
|
||||
p = (char*)hmalloc(strlen(s)+1);
|
||||
strcpy(p, s);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* (c) Heikki Hannikainen, OH7LZB <hessu@hes.iki.fi>
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HMALLOC_H
|
||||
#define HMALLOC_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Replacements for malloc, realloc and free, which never fail,
|
||||
* and might keep statistics on memory allocation...
|
||||
*/
|
||||
|
||||
extern void *hmalloc(size_t size);
|
||||
extern void *hrealloc(void *ptr, size_t size);
|
||||
extern void hfree(void *ptr);
|
||||
|
||||
extern char *hstrdup(const char *s);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,369 @@
|
|||
|
||||
/*
|
||||
* protodec.c
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h> /* String function definitions */
|
||||
#include "callbacks.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "protodec.h"
|
||||
#include "hmalloc.h"
|
||||
|
||||
decoder_on_nmea_sentence_received on_nmea_sentence_received=NULL;
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
void protodec_initialize(struct demod_state_t *d, struct serial_state_t *serial, char chanid)
|
||||
{
|
||||
memset(d, 0, sizeof(struct demod_state_t));
|
||||
|
||||
d->chanid = chanid;
|
||||
d->serial = serial;
|
||||
|
||||
d->receivedframes = 0;
|
||||
d->lostframes = 0;
|
||||
d->lostframes2 = 0;
|
||||
|
||||
protodec_reset(d);
|
||||
|
||||
d->seqnr = 0;
|
||||
|
||||
d->buffer = hmalloc(DEMOD_BUFFER_LEN);
|
||||
d->rbuffer = hmalloc(DEMOD_BUFFER_LEN);
|
||||
d->nmea = hmalloc(NMEABUFFER_LEN);
|
||||
}
|
||||
|
||||
void protodec_deinit(struct demod_state_t *d)
|
||||
{
|
||||
hfree(d->buffer);
|
||||
hfree(d->rbuffer);
|
||||
hfree(d->nmea);
|
||||
}
|
||||
|
||||
void protodec_reset(struct demod_state_t *d)
|
||||
{
|
||||
d->state = ST_SKURR;
|
||||
d->nskurr = 0;
|
||||
d->ndata = 0;
|
||||
d->npreamble = 0;
|
||||
d->nstartsign = 0;
|
||||
d->nstopsign = 0;
|
||||
d->antallpreamble = 0;
|
||||
d->antallenner = 0;
|
||||
d->last = 0;
|
||||
d->bitstuff = 0;
|
||||
d->bufferpos = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates CRC-checksum
|
||||
*/
|
||||
|
||||
unsigned short protodec_sdlc_crc(const unsigned char *data, unsigned len)
|
||||
{
|
||||
unsigned short c, crc = 0xffff;
|
||||
|
||||
while (len--)
|
||||
for (c = 0x100 + *data++; c > 1; c >>= 1)
|
||||
if ((crc ^ c) & 1)
|
||||
crc = (crc >> 1) ^ 0x8408;
|
||||
else
|
||||
crc >>= 1;
|
||||
return ~crc;
|
||||
|
||||
}
|
||||
|
||||
int protodec_calculate_crc(int length_bits, struct demod_state_t *d)
|
||||
{
|
||||
int length_bytes;
|
||||
unsigned char *buf;
|
||||
int buflen;
|
||||
int i, j, x;
|
||||
unsigned char tmp;
|
||||
|
||||
if (length_bits <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
length_bytes = length_bits / 8;
|
||||
buflen = length_bytes + 2;
|
||||
|
||||
/* what is this? */
|
||||
buf = (unsigned char *) hmalloc(sizeof(*buf) * buflen);
|
||||
for (j = 0; j < buflen; j++) {
|
||||
tmp = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
tmp |= (((d->buffer[i + 8 * j]) << (i)));
|
||||
buf[j] = tmp;
|
||||
}
|
||||
|
||||
/* ok, here's the actual CRC calculation */
|
||||
unsigned short crc = protodec_sdlc_crc(buf, buflen);
|
||||
//DBG(printf("CRC: %04x\n",crc));
|
||||
|
||||
/* what is this? */
|
||||
memset(d->rbuffer, 0, DEMOD_BUFFER_LEN);
|
||||
for (j = 0; j < length_bytes; j++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
x = j * 8 + i;
|
||||
if (x >= DEMOD_BUFFER_LEN) {
|
||||
hfree(buf);
|
||||
return 0;
|
||||
} else {
|
||||
d->rbuffer[x] = (buf[j] >> (7 - i)) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hfree(buf);
|
||||
|
||||
return (crc == 0x0f47);
|
||||
}
|
||||
|
||||
unsigned long protodec_henten(int from, int size, unsigned char *frame)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned long tmp = 0;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
tmp |= (frame[from + i]) << (size - 1 - i);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void protodec_generate_nmea(struct demod_state_t *d, int bufferlen, int fillbits, time_t received_t)
|
||||
{
|
||||
int senlen;
|
||||
int pos;
|
||||
int k, offset;
|
||||
int m;
|
||||
unsigned char sentences, sentencenum, nmeachk, letter;
|
||||
|
||||
//6bits to nmea-ascii. One sentence len max 82char
|
||||
//inc. head + tail.This makes inside datamax 62char multipart, 62 single
|
||||
senlen = 56; //this is normally not needed.For testing only. May be fixed number
|
||||
if (bufferlen <= (senlen * 6)) {
|
||||
sentences = 1;
|
||||
} else {
|
||||
sentences = bufferlen / (senlen * 6);
|
||||
//sentences , if overflow put one more
|
||||
if (bufferlen % (senlen * 6) != 0)
|
||||
sentences++;
|
||||
};
|
||||
|
||||
sentencenum = 0;
|
||||
pos = 0;
|
||||
offset = (sentences>1) ? 15 : 14;
|
||||
do {
|
||||
k = offset; //leave room for nmea header
|
||||
while (k < senlen + offset && bufferlen > pos) {
|
||||
letter = (unsigned char)protodec_henten(pos, 6, d->rbuffer);
|
||||
// 6bit-to-ascii conversion by IEC
|
||||
letter += (letter < 40) ? 48 : 56;
|
||||
d->nmea[k] = letter;
|
||||
pos += 6;
|
||||
k++;
|
||||
}
|
||||
sentencenum++;
|
||||
|
||||
memcpy(&d->nmea[0], "!AIVDM,0,0,", 11);
|
||||
d->nmea[7] += sentences;
|
||||
d->nmea[9] += sentencenum;
|
||||
|
||||
memcpy(&d->nmea[k], ",0*00\0", 6);
|
||||
|
||||
if (sentences > 1) {
|
||||
d->nmea[11] = '0' + d->seqnr;
|
||||
d->nmea[12] = ',';
|
||||
d->nmea[13] = d->chanid;
|
||||
d->nmea[14] = ',';
|
||||
if (sentencenum == sentences) d->nmea[k + 1] = '0' + fillbits;
|
||||
} else {
|
||||
d->nmea[11] = ',';
|
||||
d->nmea[12] = d->chanid;
|
||||
d->nmea[13] = ',';
|
||||
}
|
||||
|
||||
m = 1;
|
||||
nmeachk = d->nmea[m++];
|
||||
while (d->nmea[m] != '*') nmeachk ^= d->nmea[m++];
|
||||
|
||||
sprintf(&d->nmea[k + 3], "%02X\r\n", nmeachk);
|
||||
if (on_nmea_sentence_received != NULL)
|
||||
on_nmea_sentence_received(d->nmea, k+7, sentences, sentencenum);
|
||||
} while (sentencenum < sentences);
|
||||
}
|
||||
|
||||
void protodec_getdata(int bufferlen, struct demod_state_t *d)
|
||||
{
|
||||
unsigned char type = protodec_henten(0, 6, d->rbuffer);
|
||||
if (type < 1 || type > MAX_AIS_PACKET_TYPE /* 9 */)
|
||||
return;
|
||||
// unsigned long mmsi = protodec_henten(8, 30, d->rbuffer);
|
||||
int fillbits = 0;
|
||||
int k;
|
||||
time_t received_t;
|
||||
time(&received_t);
|
||||
|
||||
if (bufferlen % 6 > 0) {
|
||||
fillbits = 6 - (bufferlen % 6);
|
||||
for (k = bufferlen; k < bufferlen + fillbits; k++)
|
||||
d->rbuffer[k] = 0;
|
||||
|
||||
bufferlen = bufferlen + fillbits;
|
||||
}
|
||||
|
||||
protodec_generate_nmea(d, bufferlen, fillbits, received_t);
|
||||
|
||||
d->seqnr++;
|
||||
if (d->seqnr > 9)
|
||||
d->seqnr = 0;
|
||||
|
||||
if (type < 1 || type > MAX_AIS_PACKET_TYPE)
|
||||
return; // unsupported packet type
|
||||
}
|
||||
|
||||
void protodec_decode(char *in, int count, struct demod_state_t *d)
|
||||
{
|
||||
int i = 0;
|
||||
int bufferlength, correct;
|
||||
|
||||
while (i < count) {
|
||||
switch (d->state) {
|
||||
case ST_DATA:
|
||||
if (d->bitstuff) {
|
||||
if (in[i] == 1) {
|
||||
d->state = ST_STOPSIGN;
|
||||
d->ndata = 0;
|
||||
d->bitstuff = 0;
|
||||
} else {
|
||||
d->ndata++;
|
||||
d->last = in[i];
|
||||
d->bitstuff = 0;
|
||||
}
|
||||
} else {
|
||||
if (in[i] == d->last && in[i] == 1) {
|
||||
d->antallenner++;
|
||||
if (d->antallenner == 4) {
|
||||
d->bitstuff = 1;
|
||||
d->antallenner = 0;
|
||||
}
|
||||
|
||||
} else
|
||||
d->antallenner = 0;
|
||||
|
||||
d->buffer[d->bufferpos] = in[i];
|
||||
d->bufferpos++;
|
||||
d->ndata++;
|
||||
|
||||
if (d->bufferpos >= 449) {
|
||||
protodec_reset(d);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_SKURR:
|
||||
if (in[i] != d->last)
|
||||
d->antallpreamble++;
|
||||
else
|
||||
d->antallpreamble = 0;
|
||||
d->last = in[i];
|
||||
if (d->antallpreamble > 14 && in[i] == 0) {
|
||||
d->state = ST_PREAMBLE;
|
||||
d->nskurr = 0;
|
||||
d->antallpreamble = 0;
|
||||
}
|
||||
d->nskurr++;
|
||||
break;
|
||||
|
||||
case ST_PREAMBLE:
|
||||
if (in[i] != d->last && d->nstartsign == 0) {
|
||||
d->antallpreamble++;
|
||||
} else {
|
||||
if (in[i] == 1) {
|
||||
if (d->nstartsign == 0) {
|
||||
d->nstartsign = 3;
|
||||
d->last = in[i];
|
||||
} else if (d->nstartsign == 5) {
|
||||
d->nstartsign++;
|
||||
d->npreamble = 0;
|
||||
d->antallpreamble = 0;
|
||||
d->state = ST_STARTSIGN;
|
||||
} else {
|
||||
d->nstartsign++;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (d->nstartsign == 0) {
|
||||
d->nstartsign = 1;
|
||||
} else {
|
||||
protodec_reset(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
d->npreamble++;
|
||||
break;
|
||||
|
||||
case ST_STARTSIGN:
|
||||
if (d->nstartsign >= 7) {
|
||||
if (in[i] == 0) {
|
||||
d->state = ST_DATA;
|
||||
d->nstartsign = 0;
|
||||
d->antallenner = 0;
|
||||
memset(d->buffer, 0, DEMOD_BUFFER_LEN);
|
||||
d->bufferpos = 0;
|
||||
} else {
|
||||
protodec_reset(d);
|
||||
}
|
||||
|
||||
} else if (in[i] == 0) {
|
||||
protodec_reset(d);
|
||||
}
|
||||
d->nstartsign++;
|
||||
break;
|
||||
|
||||
case ST_STOPSIGN:
|
||||
bufferlength = d->bufferpos - 6 - 16;
|
||||
if (in[i] == 0 && bufferlength > 0) {
|
||||
correct = protodec_calculate_crc(bufferlength, d);
|
||||
if (correct) {
|
||||
d->receivedframes++;
|
||||
protodec_getdata(bufferlength, d);
|
||||
} else {
|
||||
d->lostframes++;
|
||||
}
|
||||
} else {
|
||||
d->lostframes2++;
|
||||
}
|
||||
protodec_reset(d);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
d->last = in[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
/*
|
||||
* protodec.h
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INC_PROTODEC_H
|
||||
#define INC_PROTODEC_H
|
||||
|
||||
#define ST_SKURR 1
|
||||
#define ST_PREAMBLE 2
|
||||
#define ST_STARTSIGN 3
|
||||
#define ST_DATA 4
|
||||
#define ST_STOPSIGN 5
|
||||
|
||||
#define DEMOD_BUFFER_LEN 450
|
||||
#define MAX_AIS_PACKET_TYPE 27
|
||||
#define NMEABUFFER_LEN 100
|
||||
|
||||
struct demod_state_t {
|
||||
char chanid;
|
||||
int state;
|
||||
unsigned int offset;
|
||||
int nskurr, npreamble, nstartsign, ndata, nstopsign;
|
||||
|
||||
int antallenner;
|
||||
unsigned char *buffer;
|
||||
unsigned char *rbuffer;
|
||||
char *tbuffer;
|
||||
int bufferpos;
|
||||
char last;
|
||||
int antallpreamble;
|
||||
int bitstuff;
|
||||
int receivedframes;
|
||||
int lostframes;
|
||||
int lostframes2;
|
||||
unsigned char seqnr;
|
||||
|
||||
struct serial_state_t *serial;
|
||||
|
||||
char *nmea;
|
||||
};
|
||||
|
||||
void protodec_initialize(struct demod_state_t *d, struct serial_state_t *serial, char chanid);
|
||||
void protodec_reset(struct demod_state_t *d);
|
||||
void protodec_getdata(int bufferlengde, struct demod_state_t *d);
|
||||
void protodec_decode(char *in, int count, struct demod_state_t *d);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
/*
|
||||
* pulseaudio.c
|
||||
*
|
||||
* (c) Ruben Undheim 2012
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
#include "pulseaudio.h"
|
||||
|
||||
pa_simple *pulseaudio_initialize(unsigned char channels_number, const char *appname) {
|
||||
|
||||
pa_simple *s;
|
||||
pa_sample_spec ss;
|
||||
|
||||
ss.format = PA_SAMPLE_S16NE;
|
||||
ss.channels = channels_number;
|
||||
ss.rate = 48000;
|
||||
|
||||
s = pa_simple_new(NULL,
|
||||
(appname != NULL) ? appname : "AIS Demodulator",
|
||||
PA_STREAM_RECORD, NULL, "AIS data", &ss, NULL, NULL, NULL);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void pulseaudio_cleanup(pa_simple *s){
|
||||
pa_simple_free(s);
|
||||
}
|
||||
|
||||
int pulseaudio_read(pa_simple *s, short *buffer, int count, unsigned char channels_number){
|
||||
int number_read = pa_simple_read(s, buffer, (size_t)(count * sizeof(short) * channels_number), NULL);
|
||||
return (number_read < 0) ? -1 : count;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
/*
|
||||
* pulseaudio.h
|
||||
*
|
||||
* (c) Ruben Undheim 2012
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INC_PULSEAUDIO_H
|
||||
#define INC_PULSEAUDIO_H
|
||||
|
||||
#include <pulse/simple.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
pa_simple *pulseaudio_initialize(unsigned char channels_number, const char *appname);
|
||||
|
||||
void pulseaudio_cleanup(pa_simple *s);
|
||||
|
||||
int pulseaudio_read(pa_simple *s, short *buffer, int count, unsigned char channels_number);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* INC_PULSEAUDIO_H */
|
|
@ -0,0 +1,147 @@
|
|||
|
||||
/*
|
||||
* receiver.c
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
* (c) Heikki Hannikainen 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "receiver.h"
|
||||
#include "hmalloc.h"
|
||||
#include "filter.h"
|
||||
|
||||
static int sound_levellog=1;
|
||||
|
||||
receiver_on_level_changed on_sound_level_changed=NULL;
|
||||
|
||||
static float coeffs[]={
|
||||
2.5959e-55, 2.9479e-49, 1.4741e-43, 3.2462e-38, 3.1480e-33,
|
||||
1.3443e-28, 2.5280e-24, 2.0934e-20, 7.6339e-17, 1.2259e-13,
|
||||
8.6690e-11, 2.6996e-08, 3.7020e-06, 2.2355e-04, 5.9448e-03,
|
||||
6.9616e-02, 3.5899e-01, 8.1522e-01, 8.1522e-01, 3.5899e-01,
|
||||
6.9616e-02, 5.9448e-03, 2.2355e-04, 3.7020e-06, 2.6996e-08,
|
||||
8.6690e-11, 1.2259e-13, 7.6339e-17, 2.0934e-20, 2.5280e-24,
|
||||
1.3443e-28, 3.1480e-33, 3.2462e-38, 1.4741e-43, 2.9479e-49,
|
||||
2.5959e-55
|
||||
};
|
||||
#define COEFFS_L 36
|
||||
|
||||
|
||||
struct receiver *init_receiver(char name, int num_ch, int ch_ofs)
|
||||
{
|
||||
struct receiver *rx;
|
||||
|
||||
rx = (struct receiver *) hmalloc(sizeof(struct receiver));
|
||||
memset(rx, 0, sizeof(struct receiver));
|
||||
|
||||
rx->filter = filter_init(COEFFS_L, coeffs);
|
||||
|
||||
rx->decoder = hmalloc(sizeof(struct demod_state_t));
|
||||
protodec_initialize(rx->decoder, NULL, name);
|
||||
|
||||
rx->name = name;
|
||||
rx->lastbit = 0;
|
||||
rx->num_ch = num_ch;
|
||||
rx->ch_ofs = ch_ofs;
|
||||
rx->pll = 0;
|
||||
rx->pllinc = 0x10000 / 5;
|
||||
rx->prev = 0;
|
||||
rx->last_levellog = 0;
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
void free_receiver(struct receiver *rx)
|
||||
{
|
||||
if (rx) {
|
||||
filter_free(rx->filter);
|
||||
hfree(rx);
|
||||
}
|
||||
}
|
||||
|
||||
#define INC 16
|
||||
#define FILTERED_LEN 8192
|
||||
|
||||
void receiver_run(struct receiver *rx, short *buf, int len)
|
||||
{
|
||||
float out;
|
||||
int curr, bit;
|
||||
char b;
|
||||
short maxval = 0;
|
||||
int level_distance;
|
||||
float level;
|
||||
int rx_num_ch = rx->num_ch;
|
||||
float filtered[FILTERED_LEN];
|
||||
int i;
|
||||
|
||||
/* len is number of samples available in buffer for each
|
||||
* channels - something like 1024, regardless of number of channels */
|
||||
|
||||
buf += rx->ch_ofs;
|
||||
|
||||
if (len > FILTERED_LEN)
|
||||
abort();
|
||||
|
||||
maxval = filter_run_buf(rx->filter, buf, filtered, rx_num_ch, len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
out = filtered[i];
|
||||
curr = (out > 0);
|
||||
|
||||
if ((curr ^ rx->prev) == 1) {
|
||||
if (rx->pll < (0x10000 / 2)) {
|
||||
rx->pll += rx->pllinc / INC;
|
||||
} else {
|
||||
rx->pll -= rx->pllinc / INC;
|
||||
}
|
||||
}
|
||||
rx->prev = curr;
|
||||
|
||||
rx->pll += rx->pllinc;
|
||||
|
||||
if (rx->pll > 0xffff) {
|
||||
/* slice */
|
||||
bit = (out > 0);
|
||||
/* nrzi decode */
|
||||
b = !(bit ^ rx->lastbit);
|
||||
/* feed to the decoder */
|
||||
protodec_decode(&b, 1, rx->decoder);
|
||||
|
||||
rx->lastbit = bit;
|
||||
rx->pll &= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate level, and log it */
|
||||
level = (float)maxval / (float)32768 * (float)100;
|
||||
level_distance = time(NULL) - rx->last_levellog;
|
||||
|
||||
if (level > 95.0 && (level_distance >= 30 || level_distance >= sound_levellog)) {
|
||||
if (on_sound_level_changed != NULL) on_sound_level_changed(level, rx->ch_ofs, 1);
|
||||
time(&rx->last_levellog);
|
||||
} else if (sound_levellog != 0 && level_distance >= sound_levellog) {
|
||||
if (on_sound_level_changed != NULL) on_sound_level_changed(level, rx->ch_ofs, 0);
|
||||
time(&rx->last_levellog);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
/*
|
||||
* receiver.h
|
||||
*
|
||||
* (c) Ruben Undheim 2008
|
||||
* (c) Heikki Hannikainen 2008
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INC_RECEIVER_H
|
||||
#define INC_RECEIVER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "protodec.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
struct receiver {
|
||||
struct filter *filter;
|
||||
char name;
|
||||
int lastbit;
|
||||
int num_ch;
|
||||
int ch_ofs;
|
||||
unsigned int pll;
|
||||
unsigned int pllinc;
|
||||
struct demod_state_t *decoder;
|
||||
int prev;
|
||||
time_t last_levellog;
|
||||
};
|
||||
|
||||
extern struct receiver *init_receiver(char name, int num_ch, int ch_ofs);
|
||||
extern void free_receiver(struct receiver *rx);
|
||||
|
||||
extern void receiver_run(struct receiver *rx, short *buf, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
#include "winmm_input.h"
|
||||
#include <ksmedia.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef EXTENSIBLE
|
||||
#define _KSDATAFORMAT_SUBTYPE_PCM (GUID) {0x00000001,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}}
|
||||
#endif
|
||||
|
||||
static WAVEHDR wave_chunk[WAVE_BUFFERS];
|
||||
static LPWAVEHDR current;
|
||||
static unsigned int buffer_size=0;
|
||||
|
||||
static void CALLBACK waveInProc( // wave in I/O completion procedure
|
||||
HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2
|
||||
) {
|
||||
switch (uMsg) {
|
||||
case WIM_DATA:
|
||||
current = (LPWAVEHDR)dwParam1;
|
||||
SetEvent((HANDLE)dwInstance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int winmm_init(unsigned int devId,
|
||||
LPHWAVEIN device,
|
||||
int channels,
|
||||
int bytesCount,
|
||||
HANDLE *eventHandler
|
||||
) {
|
||||
|
||||
*eventHandler=CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (*eventHandler == NULL) return 0;
|
||||
|
||||
#ifndef EXTENSIBLE
|
||||
WAVEFORMATEX Format;
|
||||
Format.cbSize = 0;
|
||||
Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
Format.nChannels = channels;
|
||||
Format.wBitsPerSample = 16;
|
||||
Format.nSamplesPerSec = 48000L;
|
||||
Format.nBlockAlign = Format.nChannels * Format.wBitsPerSample / 8;
|
||||
Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;
|
||||
LPWAVEFORMATEX pFmt=&Format;
|
||||
#else
|
||||
WAVEFORMATEXTENSIBLE fmt;
|
||||
fmt.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
|
||||
fmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
fmt.Format.nChannels = channels;
|
||||
fmt.Format.wBitsPerSample = 16;
|
||||
fmt.Format.nSamplesPerSec = 48000L;
|
||||
fmt.Format.nBlockAlign = fmt.Format.nChannels * fmt.Format.wBitsPerSample / 8;
|
||||
fmt.Format.nAvgBytesPerSec = fmt.Format.nSamplesPerSec * fmt.Format.nBlockAlign;
|
||||
fmt.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
|
||||
fmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
fmt.Samples.wReserved=0;
|
||||
fmt.Samples.wValidBitsPerSample=16;
|
||||
LPWAVEFORMATEX pFmt=&fmt.Format;
|
||||
#endif
|
||||
|
||||
MMRESULT err = waveInOpen(device, devId, pFmt, (DWORD)waveInProc, (DWORD)*eventHandler, CALLBACK_FUNCTION);
|
||||
if (err == MMSYSERR_NOERROR) {
|
||||
buffer_size=sizeof(WAVEHDR);
|
||||
size_t i;
|
||||
for (i=0; i<WAVE_BUFFERS; i++) {
|
||||
ZeroMemory(&wave_chunk[i], buffer_size);
|
||||
wave_chunk[i].lpData = malloc(bytesCount);
|
||||
wave_chunk[i].dwBufferLength = bytesCount;
|
||||
wave_chunk[i].dwUser = pFmt->nBlockAlign;
|
||||
ZeroMemory(wave_chunk[i].lpData, wave_chunk[i].dwBufferLength);
|
||||
if (waveInPrepareHeader(*device, &wave_chunk[i], buffer_size) == MMSYSERR_NOERROR) {
|
||||
waveInAddBuffer(*device, &wave_chunk[i], buffer_size);
|
||||
} else return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int winmm_getRecorded(LPHWAVEIN device, char *out) {
|
||||
int number=current->dwBytesRecorded/current->dwUser;
|
||||
if (number > 0) {
|
||||
memcpy(out, current->lpData, current->dwBytesRecorded);
|
||||
}
|
||||
waveInUnprepareHeader(*device, current, buffer_size);
|
||||
current->dwBytesRecorded=0;
|
||||
current->dwFlags=0;
|
||||
waveInPrepareHeader(*device, current, buffer_size);
|
||||
waveInAddBuffer(*device, current, buffer_size);
|
||||
current=NULL;
|
||||
return number;
|
||||
}
|
||||
|
||||
void winmm_cleanup(LPHWAVEIN device, HANDLE *eventHandler) {
|
||||
if (device != NULL) {
|
||||
waveInStop(*device);
|
||||
size_t i;
|
||||
for (i=0; i<WAVE_BUFFERS; i++) {
|
||||
waveInUnprepareHeader(*device, &wave_chunk[i], wave_chunk[i].dwBufferLength);
|
||||
}
|
||||
waveInClose(*device);
|
||||
*device=0;
|
||||
if (*eventHandler != NULL) {
|
||||
CloseHandle(*eventHandler);
|
||||
eventHandler=NULL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <mmreg.h>
|
||||
|
||||
//#ifdef EXTENSIBLE
|
||||
#define WAVE_BUFFERS 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int winmm_init(unsigned int devId,
|
||||
LPHWAVEIN device,
|
||||
int channels,
|
||||
int bytesCount,
|
||||
HANDLE *eventHandler);
|
||||
|
||||
int winmm_getRecorded(LPHWAVEIN device, char *out);
|
||||
void winmm_cleanup(LPHWAVEIN device, HANDLE *eventHandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* main.cpp -- AIS Decoder
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
* Astra Paging Ltd / AISHub (info@aishub.net)
|
||||
*
|
||||
* AISDecoder 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AISDecoder uses parts of GNUAIS project (http://gnuais.sourceforge.net/)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "sounddecoder.h"
|
||||
#include "callbacks.h"
|
||||
#ifdef HAVE_ALSA
|
||||
#include "alsaaudio/alsaaudio.h"
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_ALSA
|
||||
#define HELP_AUDIO_DEVICE "-D\tALSA input device\n\tUse '-D list' to see all available system devices.\n"
|
||||
#else
|
||||
#define HELP_AUDIO_DEVICE ""
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
#ifdef HAVE_ALSA
|
||||
#define HELP_AUDIO_DRIVERS "pulse,alsa,file"
|
||||
#else
|
||||
#define HELP_AUDIO_DRIVERS "pulse,file"
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAVE_ALSA
|
||||
#define HELP_AUDIO_DRIVERS "alsa,file"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define HELP_AUDIO_DRIVERS "winmm,file"
|
||||
#define HELP_AUDIO_DEVICE "-D\tNumeric value for input device (default WAVE_MAPPER)\n\tUse '-D list' to see all available system devices.\n"
|
||||
#endif
|
||||
|
||||
#define HELP_MSG \
|
||||
"Usage: " PROJECT_NAME " -h hostname -p port -a " HELP_AUDIO_DRIVERS " [-f /path/file.raw] [-l]\n\n"\
|
||||
"-h\tDestination host or IP address\n"\
|
||||
"-p\tDestination UDP port\n"\
|
||||
"-a\tAudio driver [" HELP_AUDIO_DRIVERS "]\n" HELP_AUDIO_DEVICE\
|
||||
"-c\tSound channels [stereo,mono,left,right] (default stereo)\n"\
|
||||
"-f\tFull path to 48kHz raw audio file\n"\
|
||||
"-l\tLog sound levels to console (stderr)\n"\
|
||||
"-d\tLog NMEA sentences to console (stderr)\n"\
|
||||
"-H\tDisplay this help\n"
|
||||
|
||||
#define MAX_BUFFER_LENGTH 2048
|
||||
static char buffer[MAX_BUFFER_LENGTH];
|
||||
static unsigned int buffer_count=0;
|
||||
|
||||
#ifdef WIN32
|
||||
WSADATA wsaData;
|
||||
void printInDevices() {
|
||||
unsigned int count = waveInGetNumDevs();
|
||||
WAVEINCAPS caps;
|
||||
unsigned int i = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) {
|
||||
fprintf(stderr, "%u: %s\r\n", i, caps.szPname);
|
||||
} else {
|
||||
fprintf(stderr, "Can't read devices\r\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
void printInDevices() {
|
||||
char **hints;
|
||||
/* Enumerate sound devices */
|
||||
int err = snd_device_name_hint(0, "pcm", (void***)&hints);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Can't read data\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char** n = hints;
|
||||
while (*n != NULL) {
|
||||
char *name = snd_device_name_get_hint(*n, "NAME");
|
||||
char *desc = snd_device_name_get_hint(*n, "DESC");
|
||||
char *type = snd_device_name_get_hint(*n, "IOID");
|
||||
if (name != NULL && desc != NULL) {
|
||||
if (type == NULL || !strcmp(type, "Input")) {
|
||||
printf("%s\n%s: <%s>\n\n", desc, type == NULL ? "Input/Output" : "Input",name);
|
||||
}
|
||||
}
|
||||
if (name != NULL) free(name);
|
||||
if (name != NULL) free(desc);
|
||||
if (name != NULL) free(type);
|
||||
n++;
|
||||
}
|
||||
|
||||
//Free hint buffer too
|
||||
snd_device_name_free_hint((void**)hints);
|
||||
snd_config_update_free_global();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int sock;
|
||||
static struct addrinfo* addr=NULL;
|
||||
|
||||
static int initSocket(const char *host, const char *portname);
|
||||
static int show_levels=0;
|
||||
static int debug_nmea=0;
|
||||
|
||||
void sound_level_changed(float level, int channel, unsigned char high) {
|
||||
if (high != 0)
|
||||
fprintf(stderr, "Level on ch %d too high: %.0f %%\n", channel, level);
|
||||
else
|
||||
fprintf(stderr, "Level on ch %d: %.0f %%\n", channel, level);
|
||||
}
|
||||
|
||||
void nmea_sentence_received(const char *sentence,
|
||||
unsigned int length,
|
||||
unsigned char sentences,
|
||||
unsigned char sentencenum) {
|
||||
if (sentences == 1) {
|
||||
if (sendto(sock, sentence, length, 0, addr->ai_addr, addr->ai_addrlen) == -1) abort();
|
||||
if (debug_nmea) fprintf(stderr, "%s", sentence);
|
||||
} else {
|
||||
if (buffer_count + length < MAX_BUFFER_LENGTH) {
|
||||
memcpy(&buffer[buffer_count], sentence, length);
|
||||
buffer_count += length;
|
||||
} else {
|
||||
buffer_count=0;
|
||||
}
|
||||
|
||||
if (sentences == sentencenum && buffer_count > 0) {
|
||||
if (sendto(sock, buffer, buffer_count, 0, addr->ai_addr, addr->ai_addrlen) == -1) abort();
|
||||
if (debug_nmea) fprintf(stderr, "%s", buffer);
|
||||
buffer_count=0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#define CMD_PARAMS_COMMON "h:p:a:lHf:dc:"
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_ALSA
|
||||
#define CMD_PARAMS CMD_PARAMS_COMMON "D:"
|
||||
#else
|
||||
#define CMD_PARAMS CMD_PARAMS_COMMON
|
||||
#endif
|
||||
#else
|
||||
#define CMD_PARAMS CMD_PARAMS_COMMON "D:"
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Sound_Channels channels = SOUND_CHANNELS_STEREO;
|
||||
char *host, *port, *file_name=NULL;
|
||||
const char *params=CMD_PARAMS;
|
||||
int alsa=0, pulse=0, file=0, winmm=0;
|
||||
int hfnd=0, pfnd=0, afnd=0;
|
||||
#ifdef WIN32
|
||||
unsigned int deviceId=WAVE_MAPPER;
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
char *alsaDevice=NULL;
|
||||
#endif
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, params)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
host = optarg;
|
||||
hfnd = 1;
|
||||
break;
|
||||
case 'p':
|
||||
port = optarg;
|
||||
pfnd = 1;
|
||||
break;
|
||||
case 'a':
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
pulse = strcmp(optarg, "pulse") == 0;
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
alsa = strcmp(optarg, "alsa") == 0;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
winmm = strcmp(optarg, "winmm") == 0;
|
||||
#endif
|
||||
file = strcmp(optarg, "file") == 0;
|
||||
afnd = 1;
|
||||
break;
|
||||
case 'c':
|
||||
if (!strcmp(optarg, "mono")) channels = SOUND_CHANNELS_MONO;
|
||||
else if (!strcmp(optarg, "left")) channels = SOUND_CHANNELS_LEFT;
|
||||
else if (!strcmp(optarg, "right")) channels = SOUND_CHANNELS_RIGHT;
|
||||
break;
|
||||
case 'l':
|
||||
show_levels = 1;
|
||||
break;
|
||||
case 'f':
|
||||
file_name = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
debug_nmea = 1;
|
||||
break;
|
||||
#ifdef WIN32
|
||||
case 'D':
|
||||
if (!strcmp(optarg, "list")) {
|
||||
printInDevices();
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
deviceId = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
case 'D':
|
||||
if (!strcmp(optarg, "list")) {
|
||||
printInDevices();
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
alsaDevice = optarg;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'H':
|
||||
default:
|
||||
fprintf(stderr, HELP_MSG);
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, HELP_MSG);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!hfnd) {
|
||||
fprintf(stderr, "Host is not set\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!pfnd) {
|
||||
fprintf(stderr, "Port is not set\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!afnd) {
|
||||
fprintf(stderr, "Audio driver is not set\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!alsa && !pulse && !winmm && !file) {
|
||||
fprintf(stderr, "Invalid audio driver\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!initSocket(host, port)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (show_levels) on_sound_level_changed=sound_level_changed;
|
||||
on_nmea_sentence_received=nmea_sentence_received;
|
||||
Sound_Driver driver = DRIVER_FILE;
|
||||
#ifdef HAVE_ALSA
|
||||
if (alsa) driver = DRIVER_ALSA;
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
if (pulse) driver = DRIVER_PULSE;
|
||||
#endif
|
||||
int OK=0;
|
||||
#ifdef WIN32
|
||||
if (!file) driver = DRIVER_WINMM;
|
||||
OK=initSoundDecoder(channels, driver, file_name, deviceId);
|
||||
#else
|
||||
#ifdef HAVE_ALSA
|
||||
OK=initSoundDecoder(channels, driver, file_name, alsaDevice);
|
||||
#else
|
||||
OK=initSoundDecoder(channels, driver, file_name);
|
||||
#endif
|
||||
#endif
|
||||
int stop=0;
|
||||
if (OK) {
|
||||
runSoundDecoder(&stop);
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", errorSoundDecoder);
|
||||
}
|
||||
freeSoundDecoder();
|
||||
freeaddrinfo(addr);
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int initSocket(const char *host, const char *portname) {
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family=AF_UNSPEC;
|
||||
hints.ai_socktype=SOCK_DGRAM;
|
||||
hints.ai_protocol=IPPROTO_UDP;
|
||||
#ifndef WIN32
|
||||
hints.ai_flags=AI_ADDRCONFIG;
|
||||
#else
|
||||
|
||||
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (iResult != 0) {
|
||||
printf("WSAStartup failed: %d\n", iResult);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int err=getaddrinfo(host, portname, &hints, &addr);
|
||||
if (err!=0) {
|
||||
fprintf(stderr, "Failed to resolve remote socket address!\n");
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
sock=socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (sock==-1) {
|
||||
fprintf(stderr, "%s",strerror(errno));
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* sounddecoder.cpp
|
||||
*
|
||||
* This file is part of AISDecoder.
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
* Astra Paging Ltd / AISHub (info@aishub.net)
|
||||
*
|
||||
* AISDecoder 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AISDecoder uses parts of GNUAIS project (http://gnuais.sourceforge.net/)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "receiver.h"
|
||||
#include "hmalloc.h"
|
||||
#ifdef HAVE_ALSA
|
||||
#include "alsaaudio/alsaaudio.h"
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
#include "pulseaudio/pulseaudio.h"
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#include "winmmaudio/winmm_input.h"
|
||||
#endif
|
||||
|
||||
#define MAX_FILENAME_SIZE 512
|
||||
#define ERROR_MESSAGE_LENGTH 1024
|
||||
#include "sounddecoder.h"
|
||||
|
||||
|
||||
char errorSoundDecoder[ERROR_MESSAGE_LENGTH];
|
||||
|
||||
static struct receiver *rx_a=NULL;
|
||||
static struct receiver *rx_b=NULL;
|
||||
|
||||
static short *buffer=NULL;
|
||||
static int buffer_l=0;
|
||||
static int buffer_read=0;
|
||||
static int channels=0;
|
||||
static Sound_Channels sound_channels;
|
||||
static Sound_Driver driver;
|
||||
static FILE *fp=NULL;
|
||||
|
||||
static void readBuffers();
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
static snd_pcm_t *pcm=NULL;
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
static pa_simple *pa_dev=NULL;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
static HWAVEIN winmm_device=0;
|
||||
static HANDLE winmm_event=0;
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_ALSA
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver,const char *file, const char *_alsaDevice) {
|
||||
#else
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver, const char *file) {
|
||||
#endif
|
||||
#else
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver, const char *file, unsigned int deviceId) {
|
||||
#endif
|
||||
sound_channels = _channels;
|
||||
driver = _driver;
|
||||
channels = sound_channels == SOUND_CHANNELS_MONO ? 1 : 2;
|
||||
errorSoundDecoder[0]=0;
|
||||
char soundFile[MAX_FILENAME_SIZE+1];
|
||||
switch (driver) {
|
||||
case DRIVER_FILE:
|
||||
strncpy(soundFile, file, MAX_FILENAME_SIZE);
|
||||
soundFile[MAX_FILENAME_SIZE]=0;
|
||||
fp = fopen(soundFile, "rb");
|
||||
if (fp) {
|
||||
buffer_l = 1024;
|
||||
int extra = buffer_l % 5;
|
||||
buffer_l -= extra;
|
||||
buffer = (short *) hmalloc(buffer_l * sizeof(short) * channels);
|
||||
} else {
|
||||
strcpy(errorSoundDecoder, "Can't open raw file for read");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
case DRIVER_PULSE:
|
||||
if((pa_dev = pulseaudio_initialize(channels, NULL)) == NULL){
|
||||
pa_dev=NULL;
|
||||
strcpy(errorSoundDecoder, "Can't initialize pulse audio");
|
||||
return 0;
|
||||
} else {
|
||||
buffer_l = 1024;
|
||||
int extra = buffer_l % 5;
|
||||
buffer_l -= extra;
|
||||
buffer = (short *) hmalloc(buffer_l * sizeof(short) * channels);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
case DRIVER_ALSA:
|
||||
if (snd_pcm_open(&pcm, (_alsaDevice != NULL ? _alsaDevice : "default"), SND_PCM_STREAM_CAPTURE, 0) < 0 ) {
|
||||
strcpy(errorSoundDecoder, "Can't open default capture device");
|
||||
return 0;
|
||||
} else {
|
||||
if (input_initialize(pcm, &buffer, &buffer_l, channels, errorSoundDecoder) < 0) return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
case DRIVER_WINMM:
|
||||
buffer_l = 4096;
|
||||
int buffer_len_in_bytes = buffer_l * sizeof(short) * channels;
|
||||
buffer = (short *) hmalloc(buffer_len_in_bytes);
|
||||
if (!winmm_init(deviceId, &winmm_device, channels, buffer_len_in_bytes, &winmm_event)) {
|
||||
strcpy(errorSoundDecoder, "Can't initialize windows audio");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sound_channels == SOUND_CHANNELS_MONO) {
|
||||
rx_a = init_receiver('A', 1, 0);
|
||||
} else {
|
||||
rx_a = init_receiver('A', 2, 0);
|
||||
rx_b = init_receiver('B', 2, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void runSoundDecoder(int *stop) {
|
||||
#ifdef WIN32
|
||||
waveInStart(winmm_device);
|
||||
#endif
|
||||
while (!*stop) {
|
||||
switch (driver) {
|
||||
case DRIVER_FILE:
|
||||
buffer_read = fread(buffer, channels * sizeof(short), buffer_l, fp);
|
||||
if (buffer_read <= 0) *stop = 1;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
case DRIVER_PULSE:
|
||||
buffer_read = pulseaudio_read(pa_dev, buffer, buffer_l, channels);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
case DRIVER_ALSA:
|
||||
buffer_read = alsa_read(pcm, buffer, buffer_l);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
case DRIVER_WINMM:
|
||||
buffer_read=0;
|
||||
switch(WaitForSingleObject(winmm_event, 2000)) {
|
||||
case WAIT_TIMEOUT:
|
||||
buffer_read=0;
|
||||
break;
|
||||
case WAIT_OBJECT_0:
|
||||
buffer_read = winmm_getRecorded(&winmm_device, (char*)buffer);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
ResetEvent(winmm_event);
|
||||
#endif
|
||||
}
|
||||
readBuffers();
|
||||
}
|
||||
#ifdef WIN32
|
||||
waveInStop(winmm_device);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void readBuffers() {
|
||||
if (buffer_read <= 0) return;
|
||||
if (rx_a != NULL && sound_channels != SOUND_CHANNELS_RIGHT)
|
||||
receiver_run(rx_a, buffer, buffer_read);
|
||||
|
||||
if (rx_b != NULL &&
|
||||
(sound_channels == SOUND_CHANNELS_STEREO || sound_channels == SOUND_CHANNELS_RIGHT)
|
||||
) receiver_run(rx_b, buffer, buffer_read);
|
||||
}
|
||||
|
||||
void freeSoundDecoder() {
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
if (pa_dev) {
|
||||
pulseaudio_cleanup(pa_dev);
|
||||
pa_dev=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
if (pcm != NULL) {
|
||||
input_cleanup(pcm);
|
||||
pcm = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
if (winmm_device) {
|
||||
winmm_cleanup(&winmm_device, &winmm_event);
|
||||
}
|
||||
#endif
|
||||
if (fp != NULL) {
|
||||
fclose(fp);
|
||||
fp=NULL;
|
||||
}
|
||||
|
||||
if (rx_a != NULL) {
|
||||
free_receiver(rx_a);
|
||||
rx_a=NULL;
|
||||
}
|
||||
|
||||
if (rx_b != NULL) {
|
||||
free_receiver(rx_b);
|
||||
rx_b=NULL;
|
||||
}
|
||||
|
||||
if (buffer != NULL) {
|
||||
hfree(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef SOUNDDECODER_H
|
||||
#define SOUNDDECODER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SOUND_CHANNELS_MONO,
|
||||
SOUND_CHANNELS_STEREO,
|
||||
SOUND_CHANNELS_LEFT,
|
||||
SOUND_CHANNELS_RIGHT
|
||||
} Sound_Channels;
|
||||
|
||||
typedef enum {
|
||||
#ifdef HAVE_ALSA
|
||||
DRIVER_ALSA,
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
DRIVER_PULSE,
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
DRIVER_WINMM,
|
||||
#endif
|
||||
DRIVER_FILE
|
||||
} Sound_Driver;
|
||||
|
||||
extern char errorSoundDecoder[];
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_ALSA
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver,const char *file, const char *_alsaDevice);
|
||||
#else
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver, const char *file);
|
||||
#endif
|
||||
#else
|
||||
int initSoundDecoder(const Sound_Channels _channels, const Sound_Driver _driver, const char *file, unsigned int deviceId);
|
||||
#endif
|
||||
void runSoundDecoder(int *stop);
|
||||
void freeSoundDecoder();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // SOUNDDECODER_H
|
Loading…
Reference in New Issue