Rename fdmdv2 to freedv.

pull/2/head
hobbes1069 2015-08-13 13:07:43 +00:00
commit a362d8ebe7
73 changed files with 16203 additions and 0 deletions

487
CMakeLists.txt 100644
View File

@ -0,0 +1,487 @@
#
# FreeDV - HF Digital Voice for Radio Amateurs
#
# CMake configuration contributed by Richard Shaw (KF5OIM)
# Please report questions, comments, problems, or patches to the freetel
# mailing list: https://lists.sourceforge.net/lists/listinfo/freetel-codec2
#
cmake_minimum_required(VERSION 2.8)
# Prevent in-source builds to protect automake/autoconf config.
# If an in-source build is attempted, you will still need to clean up a few
# files manually.
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source builds in ${CMAKE_BINARY_DIR} are not "
"allowed, please remove ./CMakeCache.txt and ./CMakeFiles/, create a "
"separate build directory and run cmake from there.")
endif("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
# Set local module path.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
project(FreeDV)
#
# Set FreeDV version and generate src/version.h
#
set(FREEDV_VERSION_MAJOR 0)
set(FREEDV_VERSION_MINOR 99)
set(FREEDV_VERSION_PATCH FALSE)
set(FREEDV_VERSION ${FREEDV_VERSION_MAJOR}.${FREEDV_VERSION_MINOR})
if(FREEDV_VERSION_PATCH)
set(FREEDV_VERSION ${FREEDV_VERSION}.${FREEDV_VERSION_PATCH})
endif()
set(FREEDV_VERSION_SUFFIX "Beta")
if(FREEDV_VERSION_SUFFIX)
set(FREEDV_VERSION_STRING "${FREEDV_VERSION} ${FREEDV_VERSION_SUFFIX}")
endif()
message(STATUS "FreeDV version: ${FREEDV_VERSION_STRING}")
configure_file(cmake/version.h.in src/version.h @ONLY)
# Set default build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
message(STATUS "Build type not specified, defaulting to ${CMAKE_BUILD_TYPE}")
endif(NOT CMAKE_BUILD_TYPE)
# Work around for not using a svn working copy.
add_definitions(-D_NO_AUTOTOOLS_)
find_program(SVNVERSION_PATH svnversion)
if(SVNVERSION_PATH)
execute_process(COMMAND ${SVNVERSION_PATH} .
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE SVN_REVISION_RESULT
OUTPUT_VARIABLE SVN_CURRENT_REVISION
ERROR_QUIET
)
else()
set(SVN_REVISION_RESULT 1)
endif()
if(SVN_REVISION_RESULT EQUAL 0)
string(STRIP ${SVN_CURRENT_REVISION} SVN_REVISION)
add_definitions(-DSVN_REVISION="${SVN_REVISION}")
else()
add_definitions(-DSVN_REVISION="Unversioned directory")
endif()
# Set default build flags.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
#
# Setup cmake options
#
set(CMAKE_VERBOSE_MAKEFILE TRUE CACHE BOOL "Verbose makefile.")
set(USE_STATIC_DEPS FALSE CACHE BOOL
"Download and build static libraries instead of system libraries.")
set(USE_STATIC_PORTAUDIO FALSE CACHE BOOL
"Download and build static portaudio instead of the system library.")
set(USE_STATIC_SNDFILE FALSE CACHE BOOL
"Download and build static sndfile instead of the system library.")
set(USE_STATIC_SAMPLERATE FALSE CACHE BOOL
"Download and build static samplerate instead of the system library.")
set(USE_STATIC_SOX FALSE CACHE BOOL
"Download and build static sox instead of the system library.")
set(USE_STATIC_CODEC2 TRUE CACHE BOOL
"Download and build static codec2 instead of the system library.")
set(USE_STATIC_SPEEXDSP TRUE CACHE BOOL
"Download and build static speex instead of the system library.")
set(BOOTSTRAP_WXWIDGETS FALSE CACHE BOOL
"Download and build static wxWidgets instead of the system library.")
if(USE_STATIC_DEPS)
set(USE_STATIC_PORTAUDIO TRUE FORCE)
set(USE_STATIC_SNDFILE TRUE FORCE)
set(USE_STATIC_SAMPLERATE TRUE FORCE)
set(USE_STATIC_SOX TRUE FORCE)
set(USE_STATIC_CODEC2 TRUE FORCE)
endif(USE_STATIC_DEPS)
#
# Pull in external wxWidgets target if performing static build.
#
if(BOOTSTRAP_WXWIDGETS)
message(STATUS "Adding wxWidgets build target...")
include(cmake/BuildWxWidgets.cmake)
endif(BOOTSTRAP_WXWIDGETS)
#
# Perform bootstrap build of wxWidgets
#
if(BOOTSTRAP_WXWIDGETS AND NOT EXISTS ${WXCONFIG})
message(STATUS "Will perform bootstrap build of wxWidgets.
After make step completes, re-run cmake and make again to perform FreeDV build.")
#
# Continue normal build if not bootstrapping wxWidgets or is already built.
#
else(BOOTSTRAP_WXWIDGETS AND NOT EXISTS ${WXCONFIG})
#
# Various hacks and work arounds for building under MinGW.
#
if(MINGW)
message(STATUS "System is MinGW.")
# Setup HOST variable.
include(cmake/MinGW.cmake)
# This sets up the exe icon for windows under mingw.
set(RES_FILES "")
set(RES_FILES "${CMAKE_SOURCE_DIR}/contrib/freedv.rc")
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
set(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
# These are DLOPEN'ed and can't be automatically pulled in by dependency.
foreach(RUNTIME
hamlib-adat.dll
hamlib-alinco.dll
hamlib-amsat.dll
hamlib-aor.dll
hamlib-ars.dll
hamlib-celestron.dll
hamlib-drake.dll
hamlib-dummy.dll
hamlib-easycomm.dll
hamlib-flexradio.dll
hamlib-fodtrack.dll
hamlib-gs232a.dll
hamlib-heathkit.dll
hamlib-icom.dll
hamlib-jrc.dll
hamlib-kachina.dll
hamlib-kenwood.dll
hamlib-kit.dll
hamlib-lowe.dll
hamlib-m2.dll
hamlib-pcr.dll
hamlib-prm80.dll
hamlib-racal.dll
hamlib-rft.dll
hamlib-rotorez.dll
hamlib-rs.dll
hamlib-sartek.dll
hamlib-skanti.dll
hamlib-spid.dll
hamlib-tapr.dll
hamlib-tentec.dll
hamlib-ts7400.dll
hamlib-tuner.dll
hamlib-uniden.dll
hamlib-winradio.dll
hamlib-wj.dll
hamlib-yaesu.dll)
message(STATUS "Checking for ${RUNTIME}")
find_library(${RUNTIME}_LIB ${RUNTIME}
PATH_SUFFIXES hamlib)
message(STATUS "runtime found: ${${RUNTIME}_LIB}")
list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${${RUNTIME}_LIB})
endforeach()
include(InstallRequiredSystemLibraries)
endif(MINGW)
# Math library is automatic on MinGW
if(UNIX)
set(CMAKE_REQUIRED_INCLUDES math.h)
set(CMAKE_REQUIRED_LIBRARIES m)
endif(UNIX)
# Find some standard headers and functions.
include(CheckIncludeFiles)
check_include_files("limits.h" HAVE_LIMITS_H)
check_include_files("stddef.h" HAVE_STDDEF_H)
check_include_files("stdlib.h" HAVE_STDLIB_H)
check_include_files("string.h" HAVE_STRING_H)
include(CheckTypeSize)
check_type_size("int" SIZEOF_INT)
include(CheckFunctionExists)
check_function_exists(floor HAVE_FLOOR)
check_function_exists(memset HAVE_MEMSET)
check_function_exists(pow HAVE_POW)
check_function_exists(sqrt HAVE_SQRT)
# fdmdv2_main.h requires patching to find config.h as it current looks in the
# source directory and the generated file goes in the binary directory.
configure_file ("${PROJECT_SOURCE_DIR}/cmake/config.h.in"
"${PROJECT_BINARY_DIR}/config.h" )
include_directories(${PROJECT_BINARY_DIR})
add_definitions(-DHAVE_CONFIG_H)
# Pthread Library
find_package(Threads REQUIRED)
message(STATUS "Threads library flags: ${CMAKE_THREAD_LIBS_INIT}")
#
# Find codec2
#
if(NOT USE_STATIC_CODEC2)
message(STATUS "Looking for codec2...")
find_package(codec2 CONFIG QUIET)
if(codec2_FOUND)
get_target_property(CODEC2_LIBRARY codec2 LOCATION)
message(STATUS " codec2 library: ${CODEC2_LIBRARY}")
message(STATUS " codec2 headers: ${codec2_INCLUDE_DIRS}")
else()
# Try to find manually
find_path(CODEC2_INCLUDE_DIRS codec2.h
PATH_SUFFIXES codec2)
find_library(CODEC2_LIBRARY NAMES codec2)
if(CODEC2_LIBRARY AND CODEC2_INCLUDE_DIRS)
message(STATUS " codec2 library: ${CODEC2_LIBRARY}")
message(STATUS " codec2 headers: ${CODEC2_INCLUDE_DIRS}")
list(APPEND FREEDV_LINK_LIBS ${CODEC2_LIBRARY})
include_directories(${CODEC2_INCLUDE_DIRS})
else()
message(FATAL_ERROR "codec2 library not found.
Linux:
Codec2 may not be in your distribution so build yourself or use the cmake option to build statically into FreeDV.
Windws:
It's easiest to use the cmake option: USE_STATIC_CODEC2"
)
endif()
endif()
else(NOT USE_STATIC_CODEC2)
message(STATUS "Will attempt static build of codec2.")
include(cmake/BuildCodec2.cmake)
endif(NOT USE_STATIC_CODEC2)
#
# Find or build portaudio Library
#
if(NOT USE_STATIC_PORTAUDIO)
message(STATUS "Looking for portaudio...")
find_package(Portaudio REQUIRED)
if(PORTAUDIO_FOUND)
message(STATUS " portaudio library: ${PORTAUDIO_LIBRARIES}")
message(STATUS " portaudio headers: ${PORTAUDIO_INCLUDE_DIRS}")
list(APPEND FREEDV_LINK_LIBS ${PORTAUDIO_LIBRARIES})
include_directories(${PORTAUDIO_INCLUDE_DIRS})
else()
message(FATAL_ERROR "portaudio library not found.
On Linux systems try installing:
portaudio-devel (RPM based systems)
libportaudio-dev (DEB based systems)
On Windows it's easiest to use the cmake option: USE_STATIC_PORTAUDIO"
)
endif()
if(NOT ${PORTAUDIO_VERSION} EQUAL 19)
message(WARNING "Portaudio versions other than 19 are known to have issues. You have been warned!")
endif()
else(NOT USE_STATIC_PORTAUDIO)
message(STATUS "Will attempt static build of portaudio.")
include(cmake/BuildPortaudio.cmake)
endif(NOT USE_STATIC_PORTAUDIO)
#
# Hamlib library
#
message(STATUS "Looking for hamlib...")
find_path(HAMLIB_INCLUDE_DIR hamlib/rig.h)
find_library(HAMLIB_LIBRARY hamlib)
message(STATUS "Hamlib library: ${HAMLIB_LIBRARY}")
message(STATUS "Hamlib headers: ${HAMLIB_INCLUDE_DIR}")
if(HAMLIB_LIBRARY AND HAMLIB_INCLUDE_DIR)
message(STATUS "Hamlib library found.")
include_directories(${HAMLIB_INCLUDE_DIR})
list(APPEND FREEDV_LINK_LIBS ${HAMLIB_LIBRARY})
else(HAMLIB_LIBRARY AND HAMLIB_INCLUDE_DIR)
message(FATAL_ERROR "hamlib not found.
On Linux systems try installing:
hamlib-devel (RPM based systems)
libhamlib-dev (DEB based systems)"
)
endif(HAMLIB_LIBRARY AND HAMLIB_INCLUDE_DIR)
#
# Samplerate Library
#
if(NOT USE_STATIC_SAMPLERATE)
message(STATUS "Looking for samplerate...")
find_library(LIBSAMPLERATE samplerate)
find_path(LIBSAMPLERATE_INCLUDE_DIR samplerate.h)
message(STATUS " samplerate library: ${LIBSAMPLERATE}")
message(STATUS " samplerate headers: ${LIBSAMPLERATE_INCLUDE_DIR}")
if(LIBSAMPLERATE AND LIBSAMPLERATE_INCLUDE_DIR)
list(APPEND FREEDV_LINK_LIBS ${LIBSAMPLERATE})
include_directories(${LIBSAMPLERATE_INCLUDE_DIR})
else(LIBSTAMPLERATE AND LIBSAMPLERATE_INCLUDE_DIR)
message(FATAL_ERROR "samplerate library not found.
On Linux systems try installing:
samplerate-devel (RPM based systems)
libsamplerate-dev (DEB based systems)
On Windows it's easiest to use the cmake option: USE_STATIC_SAMPLERATE"
)
endif(LIBSAMPLERATE AND LIBSAMPLERATE_INCLUDE_DIR)
else(NOT USE_STATIC_SAMPLERATE)
message(STATUS "Will attempt static build of samplerate.")
include(cmake/BuildSamplerate.cmake)
endif(NOT USE_STATIC_SAMPLERATE)
#
# Find sox library
#
if(NOT USE_STATIC_SOX)
message(STATUS "Looking for sox...")
find_library(LIBSOX_LIBRARY sox)
find_path(LIBSOX_INCLUDE_DIR NAMES sox/sox.h sox.h)
message(STATUS " sox library: ${LIBSOX_LIBRARY}")
message(STATUS " sox headers: ${LIBSOX_INCLUDE_DIR}")
if(LIBSOX_LIBRARY AND LIBSOX_INCLUDE_DIR)
list(APPEND FREEDV_LINK_LIBS ${LIBSOX_LIBRARY})
include_directories(${LIBSOX_INCLUDE_DIR})
else(LIBSOX_LIBRARY AND LIBSOX_INCLUDE_DIR)
message(FATAL_ERROR "sox library not found.
On Linux systems try installing:
sox-devel (RPM based systems)
libsox-dev (DEB based systems)
On Windows it's easiest to use the cmake option: USE_STATIC_SOX"
)
endif(LIBSOX_LIBRARY AND LIBSOX_INCLUDE_DIR)
else(NOT USE_STATIC_SOX)
message(STATUS "Will attempt static build of sox.")
include(cmake/BuildSox.cmake)
endif(NOT USE_STATIC_SOX)
#
# sndfile Library
#
if(NOT USE_STATIC_SNDFILE)
message(STATUS "Looking for sndfile...")
find_library(LIBSNDFILE sndfile)
find_path(LIBSNDFILE_INCLUDE_DIR sndfile.h)
message(STATUS " sndfile library: ${LIBSNDFILE}")
message(STATUS " sndfile headers: ${LIBSNDFILE_INCLUDE_DIR}")
if(LIBSNDFILE AND LIBSNDFILE_INCLUDE_DIR)
list(APPEND FREEDV_LINK_LIBS ${LIBSNDFILE})
else(LIBSNDFILE AND LIBSNDFILE_INCLUDE_DIR)
message(FATAL_ERROR "sndfile library not found.
On Linux systems try installing:
libsndfile-devel (RPM based systems)
libsndfile-dev (DEB based systems)
On Windows it's easiest to use the cmake option: USE_STATIC_SNDFILE"
)
endif(LIBSNDFILE AND LIBSNDFILE_INCLUDE_DIR)
else(NOT USE_STATIC_SNDFILE)
message(STATUS "Will attempt static build of sndfile.")
include(cmake/BuildSndfile.cmake)
endif(NOT USE_STATIC_SNDFILE)
#
# Find wxWidgets
#
if(NOT BOOTSTRAP_WXWIDGETS)
set(WXCONFIG "" CACHE FILEPATH "Location of wx-config binary.")
set(WXRC "" CACHE FILEPATH "Location of wxrc binary.")
endif(NOT BOOTSTRAP_WXWIDGETS)
#if(BOOTSTRAP_WXWIDGETS)
# set(WXCONFIG "${CMAKE_BINARY_DIR}/external/dist/bin/wx-config")
# set(WXRC "${CMAKE_BINARY_DIR}/external/dist/bin/wxrc")
# list(APPEND FREEDV_STATIC_DEPS wxWidgets)
#endif(BOOTSTRAP_WXWIDGETS)
message(STATUS "Looking for wxWidgets...")
if(WXCONFIG)
message(STATUS "wx-config: ${WXCONFIG}")
set(wxWidgets_CONFIG_EXECUTABLE ${WXCONFIG})
endif(WXCONFIG)
if(WXRC)
message(STATUS "wxrc: ${WXRC}")
set(wxWidgets_wxrc_EXECUTABLE ${WXRC})
endif(WXRC)
set(WX_VERSION_MIN 3.0.0)
find_package(wxWidgets REQUIRED core base aui html net adv)
execute_process(COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" --version
OUTPUT_VARIABLE WX_VERSION)
string(STRIP ${WX_VERSION} WX_VERSION)
if(WX_VERSION VERSION_EQUAL ${WX_VERSION_MIN}
OR WX_VERSION VERSION_GREATER ${WX_VERSION_MIN})
message(STATUS "wxWidgets version: ${WX_VERSION}")
else()
message(FATAL_ERROR "wxWidgets must be installed on your system.
Please check that wx-config is in path, the directory
where wxWidgets libraries are installed (returned by
'wx-config --libs' or 'wx-config --static --libs' command)
is in LD_LIBRARY_PATH or equivalent variable and
wxWidgets version is ${WX_VERSION_MIN} or above.")
endif()
if(wxWidgets_FOUND)
include("${wxWidgets_USE_FILE}")
list(APPEND FREEDV_LINK_LIBS ${wxWidgets_LIBRARIES})
endif(wxWidgets_FOUND)
#
# Find speex library
#
if(NOT USE_STATIC_SPEEXDSP)
message(STATUS "Looking for Speex DSP library.")
find_path(SPEEXDSP_INCLUDE_DIR speex/speex.h)
find_library(SPEEXDSP_LIBRARY speexdsp)
message(STATUS " Speex DSP headers: ${SPEEXDSP_INCLUDE_DIR}")
message(STATUS " Speex DSP library: ${SPEEXDSP_LIBRARY}")
if(SPEEXDSP_INCLUDE_DIR AND SPEEXDSP_LIBRARY)
include_directories(${SPEEXDSP_INCLUDE_DIR})
list(APPEND FREEDV_LINK_LIBS ${SPEEXDSP_LIBRARY})
else(SPEEXDSP_INCLUDE_DIR AND SPEEXDSP_LIBRARY)
message(FATAL_ERROR "Speex DSP library not found!")
endif(SPEEXDSP_INCLUDE_DIR AND SPEEXDSP_LIBRARY)
else()
message(STATUS "Will attempt static build of speex.")
include(cmake/BuildSpeex.cmake)
endif()
#Freedv
add_subdirectory(src)
# Icons and desktop file
add_subdirectory(contrib)
message(STATUS "Build type will be: ${CMAKE_BUILD_TYPE}")
#
# Cpack NSIS configuration for Windows.
#
if(WIN32)
# Detect if we're doing a 32-bit or 64-bit windows build.
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
set(CMAKE_CL_64 TRUE)
endif()
if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(CPACK_STRIP_FILES TRUE)
endif()
configure_file(cmake/GetDependencies.cmake.in cmake/GetDependencies.cmake
@ONLY
)
install(SCRIPT ${CMAKE_BINARY_DIR}/cmake/GetDependencies.cmake)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "HF Digital Voice for Radio Amateurs")
set(CPACK_PACKAGE_VENDOR "CMake")
#set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR ${FREEDV_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${FREEDV_VERSION_MINOR})
# CPack expects a patch level version so set it here and override if we
# are actually setting one.
set(CPACK_PACKAGE_VERSION_PATCH 0)
if(FREEDV_VERSION_PATCH)
set(CPACK_PACKAGE_VERSION_PATCH ${FREEDV_VERSION_PATCH})
endif()
if(FREEDV_VERSION_SUFFIX)
set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}-${FREEDV_VERSION_SUFFIX}")
endif()
# There is a bug in NSI that does not handle full unix paths properly. Make
# sure there is at least one set of four (4) backlasshes.
#set(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\freedv.exe")
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}")
set(CPACK_NSIS_PACKAGE_NAME "FreeDV")
set(CPACK_NSIS_URL_INFO_ABOUT "http://freedv.org")
set(CPACK_NSIS_MODIFY_PATH OFF)
set(CPACK_NSIS_MENU_LINKS "http://freedv.org" "FreeDV Homepage")
include(CPack)
endif(WIN32)
endif(BOOTSTRAP_WXWIDGETS AND NOT EXISTS ${WXCONFIG})

502
COPYING 100644
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see
<http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

275
README.txt 100644
View File

@ -0,0 +1,275 @@
==================================
Building and installing on Linux
==================================
Quickstart 1
-----------
Builds static versions of wxWidgets, portaudio, codec2-dev, which are commonly
missing on many Linux systems, or of the wrong (older) version.
1/ Assuming the fdmdv2-dev source is checked out into ~/fdmdv2-dev:
$ sudo apt-get install libgtk2.0-dev libhamlib-dev libsamplerate-dev libasound2-dev libao-dev libgsm1-dev
$ cd fdmdv2-dev
$ mkdir build_linux
$ cd build_linux
$ cmake -DBOOTSTRAP_WXWIDGETS=TRUE ~/fdmdv2-dev
$ make
2/ Then you can configure FreeDV using your local codec-dev, something like:
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBOOTSTRAP_WXWIDGETS=TRUE -DCODEC2_INCLUDE_DIRS=/path/to/codec2-dev/src -DCODEC2_LIBRARY=/path/to/codec2-dev/build_linux/src/libcodec2.so -DUSE_STATIC_CODEC2=FALSE -DUSE_STATIC_PORTAUDIO=TRUE -DUSE_STATIC_SOX=TRUE ../
3/ OR build a local copy of codec2-dev:
$ cmake -DBOOTSTRAP_WXWIDGETS=TRUE -DUSE_STATIC_CODEC2=TRUE -DUSE_STATIC_PORTAUDIO=TRUE -DUSE_STATIC_SOX=TRUE ../
4/ Build and run FreeDV:
$ make
$ ./src/freedv
Quickstart 2
------------
1/ Assuming you have all the dependant libraries:
$ cd /path/to/fdmdv2
$ mkdir build_linux
$ cd build_linux
$ cmake ../ (defaults to /usr/local, use CMAKE_INSTALL_PREFIX to override)
(if no errors)
$ make
(as root)
$ make install
=======================================================
Building for Windows on Ubuntu Linux (Cross compiling)
=======================================================
1/ Install the cross compiling toolchain:
$ sudo apt-get install mingw-w64
2/ Patch cmake using: http://www.cmake.org/gitweb?p=stage/cmake.git;a=patch;h=33286235048495ceafb636d549d9a4e8891967ae
3/ Checkout a fresh copy of codec2-dev and build for Windows, pointing to the generate_codebook built by a linux build of generate_codebook, using this cmake line
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=../fdmdv2-dev/cmake/Toolchain-Ubuntu-mingw32.cmake -DUNITTEST=FALSE -DGENERATE_CODEBOOK=/home/david/codec2-dev/build_linux/src/generate_codebook
4/ Build WxWidgets
$ cd /path/to/fdmdv2-dev
$ mkdir build_windows
$ cd build_windows
$ cmake -DBOOTSTRAP_WXWIDGETS=TRUE .. -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-Ubuntu-mingw32.cmake -DCMAKE_BUILD_TYPE=Debug
$ make
5/ Download and install the Windows version of Hamlib:
$ wget http://internode.dl.sourceforge.net/project/hamlib/hamlib/1.2.15.3/hamlib-win32-1.2.15.3.zip
$ unzip hamlib-win32-1.2.15.3.zip
6/ Build All the libraries and FreeDV:
$ cmake -DBOOTSTRAP_WXWIDGETS=TRUE -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-Ubuntu-mingw32.cmake -DUSE_STATIC_PORTAUDIO=TRUE -DUSE_STATIC_SNDFILE=TRUE -DUSE_STATIC_SAMPLERATE=TRUE -DUSE_STATIC_SOX=TRUE -DUSE_STATIC_CODEC2=FALSE -DCODEC2_INCLUDE_DIRS=/home/david/tmp/codec2-dev/src -DCODEC2_LIBRARY=/home/david/tmp/codec2-dev/build_windows/src/libcodec2.dll.a -DHAMLIB_INCLUDE_DIR=hamlib-win32-1.2.15.3/include -DHAMLIB_LIBRARY=hamlib-win32-1.2.15.3/lib/gcc/libhamlib.dll.a -DCMAKE_BUILD_TYPE=Debug ..
$ make
====================================
Building and installing on Windows
====================================
The windows build is similar to linux and follows the same basic workflow,
however, while codec2 and FreeDV (fdmdv2) build well on windows, some of the
dependencies do not. For that reson current windows releases are cross-compiled
from linux.
Only MinGW is supported. While it is likely possible to perform a pure MinGW
build, installing MSYS2 will make your life easier.
CMake may not automatically detect that you're in the MSYS environment. If this
occurs you need to pass cmake the proper generator:
cmake -G"MSYS Makefiles" [other options] </path/to/source>
===============================
Bootstrapping wxWidgets build
===============================
If wxWidgets (>= 3.0) is not available then one option is to have CMake boot-
strap the build for FreeDV.
This is required because the tool wx-config is used to get the correct compiler
and linker flags of the wxWidgets components needed by FreeDV. Since this is
normally done at configure time, not during "make", it is not possible for CMake
or have this information prior to building wxWidgets.
In order to work around this issue you can "bootstrap" the wxWidgets build using
the CMake option, "BOOTSTRAP_WXWIDGETS". wxWidgets will be built using static
libraries.
NOTE: This forces "USE_STATIC_WXWIDGETS" to be true internally regarless of the
value set manually.
(from any directory, but empty directory outside of the source is prefered.)
$ cmake -DBOOTSTRAP_WXWIDGETS=TRUE /path/to/fdmdv2
$ make
(wxWidgets is downloaded and built)
$ cmake .
(wxWidgets build should be detected)
$ make
(if all goes well, as root)
$ make install
====================================
Building and installing on OSX
====================================
====================================
Building and installing on FreeBSD
====================================
As per "Quickstart 2" above but change build_linux to build_freebsd
=======
Editing
=======
Please make sure your text editor does not insert tabs, and
used indents of 4 spaces. The following .emacs code was used to
configure emacs:
(setq-default indent-tabs-mode nil)
(add-hook 'c-mode-common-hook
(function (lambda ()
(setq c-basic-offset 4)
)))
====
TODO
====
[ ] Open R&D questions
+ Goal is to develop an open source DV mode that performs comparably to SSB
[ ] Does 700 perform OK next to SSB?
+ approx same tx pk level (hard to measure exactly)
+ try some low SNR channels
+ try some fast fading/nasty channels
[ ] Is 700 speech quality acceptable?
[X] test frames
[X] freedv API support
[X] BER displayed on GUI for 700 and 1600
[X] plot error patterns for 700 and 1600
+ callback for error patterns, or poll via stats interface
[X] plot error histograms for 700 and 1600
+ map bit error to carrier, have done this in tcohpsk?
+ how to reset histogram? On error reset?
+ histogram screen ... new code?
+ test with filter
[X] Bugs
[X] resync issue
[X] equalise power on 700 and 1600
[X] research real and complex PAPR
[X] waterfall and spectrum in analog mode
[X] The waterfall in analog mode appears to quit working sometimes?
[X] On TX, intermittently PTT will cause signal to be heard in speakers. Toggle PTT or
Stop/Start toggle and then starts working.
[X] Squelch control on 1600 mode will not open up squelch to 0 (appears to be around 2 dB)
[X] space bar keys PTT when entering text info box
[X] checksum based txt reception
+ only print if valid
[X] IC7200 audio breakup
[ ] short varicode doesn't work
+ #ifdef-ed out for now
+ cld be broken in freedv_api
[X] On 700 audio sounds tinny and clicky when out of sync compared to 1600 why?
+ clue: only when analog not pressed
+ this was 7.5 to 8kHz interpolator bug
[X] spectrum and waterfall scale changes when analog pressed
[X] ocassional test frames error counter goes crazy
[ ] old Waterfall AGC
[ ] 700 syncs up to 1000Hz sine waves
+ shouldn't trigger sync logic, will be a problem with carriers
[ ] "clip" led, encourage people to adjust gain to hit that occ when speaking
[ ] Win32 record from radio time
[ ] FreeDV 700 improvements
[ ] bpf filter after clipping to remove clicks
[ ] tcohpsk first, measure PAPR, impl loss
[ ] error masking
[ ] C version
[ ] training off air? Switchable?
[ ] excitation params
[ ] training
[ ] plotting other demod stats like ch ampl and phase ests
[ ] profile with perf, different libresample routine
[ ] check for occassional freedv 700 loss of sync
+ scatter seems to jump
[ ] switchable diversity (narrowband) option
+ measure difference on a few channels
+ blog
[X] win32
[X] X-compile works
[X] basic installer
[X] Win32 installer
+ Richard has taken care of this
[ ] Small fixes
[X] Playfile bug
[X] running again
[X] bump ver number
[X] long varicode default
[X] option to _not_ require checksum, on by default
[X] default squelch 2dB
[X] scatter diagram tweaks
+ e.g. meaningful plots on fading channels in real time
[X] agc with hysteresis
+ changed to log steps
[X] longer persistance
+ changed to 6 seconds
[X] diversity addtions on 700
+ still not real obvious on plot
+ might be useful to make this switchable
[X] scatter diagram different colours/carrier
[X] remember what mode you were in
[ ] cmd line file decode
[ ] Waterfall direction
[ ] documentation or use, walk through, you tube, blog posts
[ ] Web support for Presence/spotting hooks
=================
USER GUIDE NOTES
=================
TODO: Put this in a more usable form, video tutorials etc
1/ Error Histogram. Displays BER of each carrier when in "test frame"
mode. As each QPSK carrier has 2 bits there are 2*Nc histogram
points.
Ideally all carriers will have about the same BER (+/- 20% after 5000
total bit errors). However problems can occur with filtering in the
tx path. If one carrier has less power, then it will have a higher
BER. The errors in this carrier will tend to dominate overall
BER. For example if one carrier is attenuated due to SSB filter
ripple in the tx path then the BER on that carrier will be higher.
This is bad news for DV.
Suggested usage: Transmit FreeDV in test frame mode. Use a 2nd rx
(or get a friend) to monitor your rx signal with FreeDV in test frame
mode. Adjust your rx SNR to get a BER of a few % (e.g. reduce tx power,
use a short antenna for the rx, point your beam away, adjust rx RF
gain). Monitor the error histogram for a few minutes, until you have
say 5000 total bit errors. You have a problem if the BER of any
carrier is more than 20% different from the rest.
A typical issue will be one carrier at 1.0, the others at 0.5,
indicating the poorer carrier BER is twice the larger.

View File

@ -0,0 +1,23 @@
set(SPEEXDSP_CMAKE_ARGS -DBUILD_SHARED_LIBS=FALSE -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external/dist)
if(USE_STATIC_SPEEXDSP)
list(APPEND SPEEXDSP_CMAKE_ARGS
-DSPEEXDSP_LIBRARIES=${CMAKE_BINARY_DIR}/external/dist/lib/libspeexdsp.a
-DSPEEXDSP_INCLUDE_DIR=${CMAKE_BINARY_DIR}/external/dist/include)
endif()
if(CMAKE_CROSSCOMPILING)
set(CODEC2_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
endif()
include(ExternalProject)
ExternalProject_Add(codec2
SVN_REPOSITORY https://svn.code.sf.net/p/freetel/code/codec2-dev
CMAKE_ARGS ${CODEC2_CMAKE_ARGS} ${SPEEXDSP_CMAKE_ARGS}
INSTALL_COMMAND ""
)
set(CODEC2_LIBRARIES
${CMAKE_BINARY_DIR}/codec2-prefix/src/codec2-build/src/libcodec2.a)
include_directories(${CMAKE_BINARY_DIR}/codec2-prefix/src/codec2/src)
list(APPEND FREEDV_LINK_LIBS ${CODEC2_LIBRARIES})
list(APPEND FREEDV_STATIC_DEPS codec2)

View File

@ -0,0 +1,52 @@
set(PORTAUDIO_TARBALL "pa_stable_v19_20111121")
# required linking libraries on linux. Not sure about windows.
find_library(ALSA_LIBRARIES asound)
if(UNIX AND NOT ALSA_LIBRARIES)
message(ERROR "Could not find alsa library which is required for portaudio.
On Linux systems try installing:
alsa-lib-devel (RPM based systems)
libasound2-dev (DEB based systems)"
)
endif()
# Make sure that configure knows what system we're using when cross-compiling.
if(MINGW AND CMAKE_CROSSCOMPILING)
include(cmake/MinGW.cmake)
set(CONFIGURE_COMMAND ./configure --build=${HOST} --host=${HOST} --target=${HOST} --enable-cxx --without-jack --disable-shared --prefix=${CMAKE_BINARY_DIR}/external/dist)
else()
set(CONFIGURE_COMMAND ./configure --enable-cxx --without-jack --disable-shared --prefix=${CMAKE_BINARY_DIR}/external/dist)
endif()
include(ExternalProject)
ExternalProject_Add(portaudio
URL http://www.portaudio.com/archives/${PORTAUDIO_TARBALL}.tgz
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND $(MAKE)
INSTALL_COMMAND $(MAKE) install
)
if(WIN32)
set(PORTAUDIO_LIBRARIES
${CMAKE_BINARY_DIR}/external/dist/lib/libportaudio.a
${CMAKE_BINARY_DIR}/external/dist/lib/libportaudiocpp.a
)
else(WIN32)
find_library(RT rt)
find_library(ASOUND asound)
set(PORTAUDIO_LIBRARIES
${CMAKE_BINARY_DIR}/external/dist/lib/libportaudio.a
${CMAKE_BINARY_DIR}/external/dist/lib/libportaudiocpp.a
${RT}
${ASOUND}
)
endif(WIN32)
include_directories(${CMAKE_BINARY_DIR}/external/dist/include)
# Add the portaudio library to the list of libraries that must be linked.
list(APPEND FREEDV_LINK_LIBS ${PORTAUDIO_LIBRARIES})
# Setup a dependency so that this gets built before linking to freedv.
list(APPEND FREEDV_STATIC_DEPS portaudio)

View File

@ -0,0 +1,27 @@
set(SAMPLERATE_TARBALL "libsamplerate-0.1.8")
if(MINGW AND CMAKE_CROSSCOMPILING)
set(CONFIGURE_COMMAND ./configure --build=${HOST} --host=${HOST} --target=${HOST} --prefix=${CMAKE_BINARY_DIR}/external/dist --disable-sndfile)
else()
set(CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/external/dist)
endif()
include(ExternalProject)
ExternalProject_Add(samplerate
URL http://www.mega-nerd.com/SRC/${SAMPLERATE_TARBALL}.tar.gz
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND $(MAKE)
INSTALL_COMMAND $(MAKE) install
)
if(WIN32)
set(SAMPLERATE_LIBRARIES
${CMAKE_BINARY_DIR}/external/dist/lib/libsamplerate.a)
else(WIN32)
set(SAMPLERATE_LIBRARIES
${CMAKE_BINARY_DIR}/external/dist/lib/libsamplerate.a)
endif(WIN32)
include_directories(${CMAKE_BINARY_DIR}/external/dist/include)
list(APPEND FREEDV_LINK_LIBS ${SAMPLERATE_LIBRARIES})
list(APPEND FREEDV_STATIC_DEPS samplerate)

View File

@ -0,0 +1,26 @@
set(SNDFILE_TARBALL "libsndfile-1.0.25")
if(MINGW AND CMAKE_CROSSCOMPILING)
set(CONFIGURE_COMMAND ./configure --host=${HOST} --prefix=${CMAKE_BINARY_DIR}/external/dist --disable-external-libs --disable-shared)
else()
set(CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/external/dist --disable-external-libs --disable-shared --disable-external-libs)
endif()
include(ExternalProject)
ExternalProject_Add(sndfile
URL http://www.mega-nerd.com/libsndfile/files/${SNDFILE_TARBALL}.tar.gz
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND $(MAKE) V=1
INSTALL_COMMAND $(MAKE) install
)
if(MINGW)
set(SNDFILE_LIBRARIES ${CMAKE_BINARY_DIR}/external/dist/lib/libsndfile.a)
else()
set(SNDFILE_LIBRARIES ${CMAKE_BINARY_DIR}/external/dist/lib/libsndfile.a)
endif()
include_directories(${CMAKE_BINARY_DIR}/external/dist/include)
list(APPEND FREEDV_LINK_LIBS ${SNDFILE_LIBRARIES})
list(APPEND FREEDV_STATIC_DEPS sndfile)

View File

@ -0,0 +1,48 @@
set(SOX_TARBALL "sox-14.4.1")
# required linking libraries on linux. Not sure about windows.
find_library(ALSA_LIBRARIES asound)
find_library(AO_LIBRARIES ao)
find_library(GSM_LIBRARIES gsm)
if(UNIX AND NOT ALSA_LIBRARIES)
message(ERROR "Could not find alsa library.
On Linux systems try installing:
alsa-lib-devel (RPM based systems)
libasound2-dev (DEB based systems)"
)
endif(UNIX AND NOT ALSA_LIBRARIES)
if(UNIX AND NOT AO_LIBRARIES)
message(ERROR "Could not find libao.
On Linux systems try installing:
libao-devel (RPM based systems)
libao-dev (DEB based systems)"
)
endif(UNIX AND NOT AO_LIBRARIES)
if(MINGW AND CMAKE_CROSSCOMPILING)
set(CONFIGURE_COMMAND ./configure --host=${HOST} --enable-shared=no --without-id3tag --without-png --disable-gomp --with-oggvorbis=no --with-oss=no --with-flac=no --with-amrnb=no --with-amrwb=no --with-mp3=no --with-wavpack=no --disable-dl-sndfile --with-pulseaudio=no --without-magic --with-gsm --prefix=${CMAKE_BINARY_DIR}/external/dist)
else()
set(CONFIGURE_COMMAND ./configure --enable-shared=no --without-id3tag --without-png --disable-gomp --with-oggvorbis=no --with-oss=no --with-flac=no --with-amrnb=no --with-amrwb=no --with-mp3=no --with-wavpack=no --disable-dl-sndfile --with-pulseaudio=no --without-magic --with-gsm --prefix=${CMAKE_BINARY_DIR}/external/dist)
endif()
include(ExternalProject)
ExternalProject_Add(sox
URL http://downloads.sourceforge.net/sox/${SOX_TARBALL}.tar.gz
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND $(MAKE) V=1
INSTALL_COMMAND $(MAKE) install
)
set(SOX_LIBRARIES ${CMAKE_BINARY_DIR}/external/dist/lib/libsox.a)
if(UNIX)
list(APPEND SOX_LIBRARIES ${ALSA_LIBRARIES} ${AO_LIBRARIES} ${GSM_LIBRARIES})
endif()
if(MINGW)
list(APPEND SOX_LIBRARIES winmm)
endif()
include_directories(${CMAKE_BINARY_DIR}/external/dist/include)
list(APPEND FREEDV_LINK_LIBS ${SOX_LIBRARIES})
list(APPEND FREEDV_STATIC_DEPS sox)

View File

@ -0,0 +1,26 @@
set(SPEEXDSP_TARBALL "speexdsp-1.2rc3.tar.gz")
if(MINGW AND CMAKE_CROSSCOMPILING)
include(cmake/MinGW.cmake)
set(CONFIGURE_COMMAND ./configure --host=${HOST} --prefix=${CMAKE_BINARY_DIR}/external/dist --disable-examples)
else()
set(CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/external/dist --disable-examples)
endif()
include(ExternalProject)
ExternalProject_Add(speex
URL http://downloads.xiph.org/releases/speex/${SPEEXDSP_TARBALL}
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND $(MAKE)
INSTALL_COMMAND $(MAKE) install
)
set(SPEEXDSP_LIBRARIES ${CMAKE_BINARY_DIR}/external/dist/lib/libspeexdsp.a)
include_directories(${CMAKE_BINARY_DIR}/external/dist/include)
list(APPEND FREEDV_LINK_LIBS ${SPEEXDSP_LIBRARIES})
list(APPEND FREEDV_STATIC_DEPS speex)
if(USE_STATIC_CODEC2)
add_dependencies(codec2 speex)
endif()

View File

@ -0,0 +1,43 @@
set(WXWIDGETS_TARBALL "wxWidgets-3.0.2")
# If we're cross-compiling then we need to set the target host manually.
if(MINGW AND CMAKE_CROSSCOMPILING)
include(cmake/MinGW.cmake)
endif()
# If not cross-compiling then use the built-in makefile, otherwise use standard configure.
if(MINGW AND NOT CMAKE_CROSSCOMPILING)
# set(CONFIGURE_COMMAND "true")
# set(MAKE_COMMAND $(MAKE) -C build/msw -f makefile.gcc SHARED=0 UNICODE=1 BUILD=release PREFIX=${CMAKE_BINARY_DIR}/external/dist)
set(CONFIGURE_COMMAND ./configure --disable-shared --prefix=${CMAKE_BINARY_DIR}/external/dist)
set(MAKE_COMMAND $(MAKE))
endif()
if(MINGW AND CMAKE_CROSSCOMPILING)
set(CONFIGURE_COMMAND ./configure --build=${HOST} --host=${HOST} --target=${HOST} --disable-shared --prefix=${CMAKE_BINARY_DIR}/external/dist)
set(MAKE_COMMAND $(MAKE))
endif()
if(NOT MINGW)
set(CONFIGURE_COMMAND ./configure --host=${HOST} --target=${HOST} --disable-shared --prefix=${CMAKE_BINARY_DIR}/external/dist)
set(MAKE_COMMAND $(MAKE))
endif()
include(ExternalProject)
ExternalProject_Add(wxWidgets
URL http://downloads.sourceforge.net/wxwindows/${WXWIDGETS_TARBALL}.tar.bz2
BUILD_IN_SOURCE 1
INSTALL_DIR external/dist
CONFIGURE_COMMAND ${CONFIGURE_COMMAND}
BUILD_COMMAND ${MAKE_COMMAND}
INSTALL_COMMAND $(MAKE) install
)
ExternalProject_Get_Property(wxWidgets install_dir)
message(STATUS "wxWidgets install dir: ${install_dir}")
if(NOT WXCONFIG)
set(WXCONFIG "${install_dir}/bin/wx-config")
endif()
if(EXISTS ${WXCONFIG})
set(BS_WX_DONE TRUE)
endif()

View File

@ -0,0 +1,107 @@
# - Try to find Portaudio
# Once done this will define
#
# PORTAUDIO_FOUND - system has Portaudio
# PORTAUDIO_INCLUDE_DIRS - the Portaudio include directory
# PORTAUDIO_LIBRARIES - Link these to use Portaudio
# PORTAUDIO_DEFINITIONS - Compiler switches required for using Portaudio
# PORTAUDIO_VERSION - Portaudio version
#
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
# in cache already
set(PORTAUDIO_FOUND TRUE)
else (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
if (NOT WIN32)
include(FindPkgConfig)
pkg_check_modules(PORTAUDIO2 portaudio-2.0)
endif (NOT WIN32)
if (PORTAUDIO2_FOUND)
set(PORTAUDIO_INCLUDE_DIRS
${PORTAUDIO2_INCLUDE_DIRS}
)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(PORTAUDIO_LIBRARIES "${PORTAUDIO2_LIBRARY_DIRS}/lib${PORTAUDIO2_LIBRARIES}.dylib")
else (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(PORTAUDIO_LIBRARIES
${PORTAUDIO2_LIBRARIES}
)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(PORTAUDIO_VERSION
19
)
set(PORTAUDIO_FOUND TRUE)
else (PORTAUDIO2_FOUND)
find_path(PORTAUDIO_INCLUDE_DIR
NAMES
portaudio.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(PORTAUDIO_LIBRARY
NAMES
portaudio
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
find_path(PORTAUDIO_LIBRARY_DIR
NAMES
portaudio
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(PORTAUDIO_INCLUDE_DIRS
${PORTAUDIO_INCLUDE_DIR}
)
set(PORTAUDIO_LIBRARIES
${PORTAUDIO_LIBRARY}
)
set(PORTAUDIO_LIBRARY_DIRS
${PORTAUDIO_LIBRARY_DIR}
)
set(PORTAUDIO_VERSION
18
)
if (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
set(PORTAUDIO_FOUND TRUE)
endif (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
if (PORTAUDIO_FOUND)
if (NOT Portaudio_FIND_QUIETLY)
message(STATUS "Found Portaudio: ${PORTAUDIO_LIBRARIES}")
endif (NOT Portaudio_FIND_QUIETLY)
else (PORTAUDIO_FOUND)
if (Portaudio_FIND_REQUIRED)
message(FATAL_ERROR "Could not find Portaudio")
endif (Portaudio_FIND_REQUIRED)
endif (PORTAUDIO_FOUND)
endif (PORTAUDIO2_FOUND)
# show the PORTAUDIO_INCLUDE_DIRS and PORTAUDIO_LIBRARIES variables only in the advanced view
mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES)
endif (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)

View File

@ -0,0 +1,25 @@
# As this script is run in a new cmake instance, it does not have access to
# the existing cache variables. Pass them in via the configure_file command.
set(CMAKE_BINARY_DIR @CMAKE_BINARY_DIR@)
set(CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@)
set(UNIX @UNIX@)
set(WIN32 @WIN32@)
set(CMAKE_CROSSCOMPILING @CMAKE_CROSSCOMPILING@)
set(CMAKE_FIND_LIBRARY_SUFFIXES @CMAKE_FIND_LIBRARY_SUFFIXES@)
set(CMAKE_FIND_LIBRARY_PREFIXES @CMAKE_FIND_LIBRARY_PREFIXES@)
set(CMAKE_SYSTEM_LIBRARY_PATH @CMAKE_SYSTEM_LIBRARY_PATH@)
set(CMAKE_FIND_ROOT_PATH @CMAKE_FIND_ROOT_PATH@)
set(FREEDV_EXE ${CMAKE_BINARY_DIR}/src/freedv.exe)
include(GetPrerequisites)
get_prerequisites("${FREEDV_EXE}" _deps 1 1 "" "${CMAKE_SYSTEM_LIBRARY_PATH}")
foreach(_runtime ${_deps})
message("Looking for ${_runtime}")
find_library(RUNTIME_${_runtime} ${_runtime})
message("${RUNTIME_${_runtime}}")
if(RUNTIME_${_runtime})
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin"
TYPE EXECUTABLE FILES "${RUNTIME_${_runtime}}")
endif()
endforeach()

View File

@ -0,0 +1,8 @@
# If we're cross-compiling then we need to set the target host manually.
if(MINGW AND CMAKE_CROSSCOMPILING)
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
set(HOST x86_64-w64-mingw32)
else()
set(HOST i686-w64-mingw32)
endif()
endif()

View File

@ -0,0 +1,25 @@
# Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
# *) cd build
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw32.cmake ..
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX i686-w64-mingw32)
# cross compilers to use for C and C++
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
# set 1st to dir with the cross compiler's C/C++ headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

19
cmake/config.h.in 100644
View File

@ -0,0 +1,19 @@
/*--------------------------------------------------------------------------
** This file is autogenerated from config.h.in
** during the cmake configuration of your project. If you need to make changes
** edit the original file NOT THIS FILE.
** --------------------------------------------------------------------------*/
#ifndef _CONFIGURATION_HEADER_GUARD_H_
#define _CONFIGURATION_HEADER_GUARD_H_
#define SIZEOF_INT @SIZEOF_INT@
#cmakedefine HAVE_LIMITS_H @HAVE_LIMITS_H@
#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
#cmakedefine HAVE_STDDEF_H @HAVE_STDDEF_H@
#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@
#cmakedefine HAVE_STRING_H @HAVE_STRING_H@
#cmakedefine HAVE_FLOOR @HAVE_FLOOR@
#cmakedefine HAVE_MEMSET @HAVE_MEMSET@
#cmakedefine HAVE_POW @HAVE_POW@
#cmakedefine HAVE_SQRT @HAVE_SQRT@
#endif

11
cmake/version.h.in 100644
View File

@ -0,0 +1,11 @@
#ifndef FREEDV_VER_DOT_H
#define FREEDV_VER_DOT_H 1
#define FREEDV_VERSION_MAJOR @FREEDV_VERSION_MAJOR@
#define FREEDV_VERSION_MINOR @FREEDV_VERSION_MINOR@
#define FREEDV_VERSION_PATCH @FREEDV_VERSION_PATCH@
#define FREEDV_VERSION_SUFFIX "@FREEDV_VERSION_SUFFIX@"
#define FREEDV_VERSION "@FREEDV_VERSION_STRING@"
#endif //FREEDV_VER_DOT_H

View File

@ -0,0 +1,22 @@
# Install icons if we're on most *nix systems.
if(UNIX AND NOT APPLE)
set(ICON_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor
CACHE PATH "Prefix to use for installing icons.")
install(FILES freedv48x48.png
DESTINATION ${ICON_INSTALL_PREFIX}/48x48/apps
RENAME freedv.png)
install(FILES freedv64x64.png
DESTINATION ${ICON_INSTALL_PREFIX}/64x64/apps
RENAME freedv.png)
install(FILES freedv128x128.png
DESTINATION ${ICON_INSTALL_PREFIX}/128x128/apps
RENAME freedv.png)
install(FILES freedv256x256.png
DESTINATION ${ICON_INSTALL_PREFIX}/256x256/apps
RENAME freedv.png)
set(DESKTOP_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/applications
CACHE PATH "Location to install desktop files.")
install(FILES freedv.desktop
DESTINATION ${DESKTOP_INSTALL_DIR})
endif(UNIX AND NOT APPLE)

393
contrib/LICENSE 100644
View File

@ -0,0 +1,393 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public licenses.
Notwithstanding, Creative Commons may elect to apply one of its public
licenses to material it publishes and in those instances will be
considered the "Licensor." Except for the limited purpose of indicating
that material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the public
licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=FreeDV
Exec=freedv
Icon=freedv
Type=Application
Terminal=false
Categories=GTK;GNOME;AudioVideo;Audio;HamRadio;

BIN
contrib/freedv.ico 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

View File

@ -0,0 +1 @@
id ICON "./freedv.ico"

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

13
credits.txt 100644
View File

@ -0,0 +1,13 @@
Credits (code or ideas borrowed from):
==============================================
Dave Witten and David Rowe (obviously)
Mel Whitten K0PFX (material and moral support)
Bruce Perens (cheerleader, promotion and publicity)
Mooneer Salem KG6AOV(Mac OSX Patch)
Soeren Straarup OZ2DAK (FreeBSD Port)
Don Mak
Steve Nance (K5FR)
Joel Stanley (Hamlib prototyping) and Mark Jessop (Mac OSX)
James Ahlstrom (Quisk)
FLDIGI
All the folks on the digital voice google group...

1
db/current 100644
View File

@ -0,0 +1 @@
1

2
db/format 100644
View File

@ -0,0 +1,2 @@
4
layout sharded 1000

1
db/fs-type 100644
View File

@ -0,0 +1 @@
fsfs

38
db/fsfs.conf 100644
View File

@ -0,0 +1,38 @@
### This file controls the configuration of the FSFS filesystem.
[memcached-servers]
### These options name memcached servers used to cache internal FSFS
### data. See http://www.danga.com/memcached/ for more information on
### memcached. To use memcached with FSFS, run one or more memcached
### servers, and specify each of them as an option like so:
# first-server = 127.0.0.1:11211
# remote-memcached = mymemcached.corp.example.com:11212
### The option name is ignored; the value is of the form HOST:PORT.
### memcached servers can be shared between multiple repositories;
### however, if you do this, you *must* ensure that repositories have
### distinct UUIDs and paths, or else cached data from one repository
### might be used by another accidentally. Note also that memcached has
### no authentication for reads or writes, so you must ensure that your
### memcached servers are only accessible by trusted users.
[caches]
### When a cache-related error occurs, normally Subversion ignores it
### and continues, logging an error if the server is appropriately
### configured (and ignoring it with file:// access). To make
### Subversion never ignore cache errors, uncomment this line.
# fail-stop = true
[rep-sharing]
### To conserve space, the filesystem can optionally avoid storing
### duplicate representations. This comes at a slight cost in
### performance, as maintaining a database of shared representations can
### increase commit times. The space savings are dependent upon the size
### of the repository, the number of objects it contains and the amount of
### duplication between them, usually a function of the branching and
### merging process.
###
### The following parameter enables rep-sharing in the repository. It can
### be switched on and off at will, but for best space-saving results
### should be enabled consistently over the life of the repository.
### rep-sharing is enabled by default.
# enable-rep-sharing = true

View File

@ -0,0 +1 @@
0

BIN
db/rep-cache.db 100644

Binary file not shown.

5
db/revprops/0/0 100644
View File

@ -0,0 +1,5 @@
K 8
svn:date
V 27
2012-08-21T18:27:59.389906Z
END

13
db/revprops/0/1 100644
View File

@ -0,0 +1,13 @@
K 10
svn:author
V 9
OFA-Staff
K 8
svn:date
V 27
2012-08-21T18:28:08.741468Z
K 7
svn:log
V 25
Imported folder structure
END

11
db/revs/0/0 100644
View File

@ -0,0 +1,11 @@
PLAIN
END
ENDREP
id: 0.0.r0/17
type: dir
count: 0
text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e
cpath: /
17 107

49
db/revs/0/1 100644
View File

@ -0,0 +1,49 @@
id: 3-1.0.r1/0
type: dir
count: 0
cpath: /tags
copyroot: 0 /
id: 0-1.0.r1/62
type: dir
count: 0
cpath: /trunk
copyroot: 0 /
id: 2-1.0.r1/126
type: dir
count: 0
cpath: /branches
copyroot: 0 /
PLAIN
K 8
branches
V 16
dir 2-1.0.r1/126
K 4
tags
V 14
dir 3-1.0.r1/0
K 5
trunk
V 15
dir 0-1.0.r1/62
END
ENDREP
id: 0.0.r1/306
type: dir
pred: 0.0.r0/17
count: 1
text: 1 194 99 99 7b6cc14dddba4e09be5255b475d1a0a8
cpath: /
copyroot: 0 /
_0.0.t0-0 add-dir false false /trunk
_2.0.t0-0 add-dir false false /branches
_3.0.t0-0 add-dir false false /tags
306 431

1
db/txn-current 100644
View File

@ -0,0 +1 @@
1

View File

1
db/uuid 100644
View File

@ -0,0 +1 @@
a56d66ce-6468-4744-9be7-52ce95ca47a4

0
db/write-lock 100644
View File

44
src/CMakeLists.txt 100644
View File

@ -0,0 +1,44 @@
set(FREEDV_SOURCES
dlg_audiooptions.cpp
dlg_filter.cpp
dlg_options.cpp
dlg_ptt.cpp
fdmdv2_main.cpp
fdmdv2_pa_wrapper.cpp
fdmdv2_plot.cpp
fdmdv2_plot_scalar.cpp
fdmdv2_plot_scatter.cpp
fdmdv2_plot_spectrum.cpp
fdmdv2_plot_waterfall.cpp
hamlib.cpp
topFrame.cpp
sox_biquad.c
comp.h
dlg_audiooptions.h
dlg_filter.h
dlg_options.h
dlg_ptt.h
fdmdv2_defines.h
fdmdv2_main.h
fdmdv2_pa_wrapper.h
fdmdv2_plot.h
fdmdv2_plot_scalar.h
fdmdv2_plot_scatter.h
fdmdv2_plot_spectrum.h
fdmdv2_plot_waterfall.h
hamlib.h
sox_biquad.h
sox.h
topFrame.h
version.h
)
# WIN32 is needed for Windows GUI apps and is ignored for UNIX like systems.
add_executable(freedv WIN32 ${FREEDV_SOURCES} ${RES_FILES})
target_link_libraries(freedv ${FREEDV_LINK_LIBS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if(FREEDV_STATIC_DEPS)
add_dependencies(freedv ${FREEDV_STATIC_DEPS})
endif(FREEDV_STATIC_DEPS)
install(TARGETS freedv
RUNTIME DESTINATION bin)

52
src/Makefile.win32 100644
View File

@ -0,0 +1,52 @@
# src/Makefile.win32
# David Rowe 26 Oct 2012
#
# Makefile for Win32 on msys/Mingw to help David R get up to speed
#
# $ make -f Makefile.Win32
CODEC2_PATH=$(HOME)/codec2-dev
INCLUDE_PATH=/usr/local/include
WX_CONFIG=wx-config
WX_CPPFLAGS = $(shell $(WX_CONFIG) --cxxflags) -D__WXDEBUG__
WX_LIBS = $(shell $(WX_CONFIG) --libs core, base, aui, adv, net)
SVN_REVISION=$(shell svnversion)
CODEC2_INC=$(CODEC2_PATH)/src
CODEC2_LIB=$(CODEC2_PATH)/build_win32/src/
CPP_FLAGS = -D_NO_AUTOTOOLS_ -I$(INCLUDE_PATH) $(WX_CPPFLAGS) -I$(CODEC2_INC) -I../extern/include -I. -g -Wall -DSVN_REVISION=\"$(SVN_REVISION)\"
LIBS = $(WX_LIBS) -L$(CODEC2_LIB) -lcodec2 -lm -lportaudiocpp -lportaudio -lpthread -lsndfile -lsamplerate -lhamlib -lsox -lspeexdsp
OBJS = topFrame.o \
fdmdv2_main.o \
fdmdv2_plot.o \
fdmdv2_plot_scalar.o \
fdmdv2_plot_scatter.o \
fdmdv2_plot_spectrum.o \
fdmdv2_plot_waterfall.o \
fdmdv2_pa_wrapper.o \
dlg_audiooptions.o \
dlg_ptt.o \
dlg_options.o \
dlg_filter.o \
sox_biquad.o \
hamlib.o \
../../codec2-dev/src/golay23.o
HDRS = version.h dlg_audiooptions.h dlg_ptt.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h dlg_audiooptions.h topFrame.h varicode.h ../../codec2-dev/src/golay23.h hamlib.h
all: freedv
freedv: $(OBJS)
g++ -o freedv $(OBJS) $(CPP_FLAGS) $(LIBS)
%.o: %.cpp $(HDRS) Makefile.win32
g++ $(CPP_FLAGS) -c $< -o $@
%.o: %.c $(HDRS) Makefile.win32
gcc $(CPP_FLAGS) -c $< -o $@
clean:
rm -f *.o fdmdv2

39
src/comp.h 100644
View File

@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------*\
FILE........: comp.h
AUTHOR......: David Rowe
DATE CREATED: 24/08/09
Complex number definition.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2009 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. 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 Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __COMP__
#define __COMP__
/* Complex number */
typedef struct
{
float real;
float imag;
} COMP;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
//=========================================================================
// Name: AudioInfoDisplay.h
// Purpose: Declares simple wxWidgets application with GUI
// created using wxFormBuilder.
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//=========================================================================
#ifndef __AudioOptsDialog__
#define __AudioOptsDialog__
#include "fdmdv2_main.h"
#define ID_AUDIO_OPTIONS 1000
#define AUDIO_IN 0
#define AUDIO_OUT 1
#include "portaudio.h"
#ifdef WIN32
#if PA_USE_ASIO
#include "pa_asio.h"
#endif
#endif
#include "codec2_fifo.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// AudioInfoDisplay
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class AudioInfoDisplay
{
public:
wxListCtrl* m_listDevices;
int direction;
wxTextCtrl* m_textDevice;
wxComboBox* m_cbSampleRate;
};
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// class AudioOptsDialog
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class AudioOptsDialog : public wxDialog
{
private:
protected:
PaError pa_err;
bool m_isPaInitialized;
int rxInAudioDeviceNum;
int rxOutAudioDeviceNum;
int txInAudioDeviceNum;
int txOutAudioDeviceNum;
void buildTestControls(PlotScalar **plotScalar, wxButton **btnTest,
wxPanel *parentPanel, wxBoxSizer *bSizer, wxString buttonLabel);
void plotDeviceInputForAFewSecs(int devNum, PlotScalar *plotScalar);
void plotDeviceOutputForAFewSecs(int devNum, PlotScalar *plotScalar);
int buildListOfSupportedSampleRates(wxComboBox *cbSampleRate, int devNum, int in_out);
void populateParams(AudioInfoDisplay);
void showAPIInfo();
int setTextCtrlIfDevNumValid(wxTextCtrl *textCtrl, wxListCtrl *listCtrl, int devNum);
void Pa_Init(void);
void OnDeviceSelect(wxComboBox *cbSampleRate,
wxTextCtrl *textCtrl,
int *devNum,
wxListCtrl *listCtrlDevices,
int index,
int in_out);
AudioInfoDisplay m_RxInDevices;
AudioInfoDisplay m_RxOutDevices;
AudioInfoDisplay m_TxInDevices;
AudioInfoDisplay m_TxOutDevices;
wxPanel* m_panel1;
wxNotebook* m_notebook1;
wxPanel* m_panelRx;
wxListCtrl* m_listCtrlRxInDevices;
wxStaticText* m_staticText51;
wxTextCtrl* m_textCtrlRxIn;
wxStaticText* m_staticText6;
wxComboBox* m_cbSampleRateRxIn;
wxButton* m_btnRxInTest;
PlotScalar* m_plotScalarRxIn;
wxListCtrl* m_listCtrlRxOutDevices;
wxStaticText* m_staticText9;
wxTextCtrl* m_textCtrlRxOut;
wxStaticText* m_staticText10;
wxComboBox* m_cbSampleRateRxOut;
wxButton* m_btnRxOutTest;
PlotScalar* m_plotScalarRxOut;
wxPanel* m_panelTx;
wxListCtrl* m_listCtrlTxInDevices;
wxStaticText* m_staticText12;
wxTextCtrl* m_textCtrlTxIn;
wxStaticText* m_staticText11;
wxComboBox* m_cbSampleRateTxIn;
wxButton* m_btnTxInTest;
PlotScalar* m_plotScalarTxIn;
wxListCtrl* m_listCtrlTxOutDevices;
wxStaticText* m_staticText81;
wxTextCtrl* m_textCtrlTxOut;
wxStaticText* m_staticText71;
wxComboBox* m_cbSampleRateTxOut;
wxButton* m_btnTxOutTest;
PlotScalar* m_plotScalarTxOut;
wxPanel* m_panelAPI;
wxStaticText* m_staticText7;
wxStaticText* m_textStringVer;
wxStaticText* m_staticText8;
wxStaticText* m_textIntVer;
wxStaticText* m_staticText5;
wxStaticText* m_textCDevCount;
wxStaticText* m_staticText4;
wxStaticText* m_textAPICount;
wxButton* m_btnRefresh;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Apply;
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class
//virtual void OnActivateApp( wxActivateEvent& event ) { event.Skip(); }
// virtual void OnCloseFrame( wxCloseEvent& event ) { event.Skip(); }
void OnRxInDeviceSelect( wxListEvent& event );
void OnRxInTest( wxCommandEvent& event );
void OnRxOutTest( wxCommandEvent& event );
void OnTxInTest( wxCommandEvent& event );
void OnTxOutTest( wxCommandEvent& event );
void OnRxOutDeviceSelect( wxListEvent& event );
void OnTxInDeviceSelect( wxListEvent& event );
void OnTxOutDeviceSelect( wxListEvent& event );
void OnRefreshClick( wxCommandEvent& event );
void OnApplyAudioParameters( wxCommandEvent& event );
void OnCancelAudioParameters( wxCommandEvent& event );
void OnOkAudioParameters( wxCommandEvent& event );
// Virtual event handlers, overide them in your derived class
void OnClose( wxCloseEvent& event ) { event.Skip(); }
void OnHibernate( wxActivateEvent& event ) { event.Skip(); }
void OnIconize( wxIconizeEvent& event ) { event.Skip(); }
void OnInitDialog( wxInitDialogEvent& event );
public:
AudioOptsDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Audio Config"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 300,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~AudioOptsDialog();
int ExchangeData(int inout);
};
#endif //__AudioOptsDialog__

786
src/dlg_filter.cpp 100644
View File

@ -0,0 +1,786 @@
//==========================================================================
// Name: dlg_filter.cpp
// Purpose: Dialog for controlling Codec audio filtering
// Date: Nov 25 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include "dlg_filter.h"
#define SLIDER_MAX 100
#define SLIDER_LENGTH 100
#define FILTER_MIN_MAG_DB -20.0
#define FILTER_MAX_MAG_DB 20.0
#define MAX_FREQ_BASS 600.00
#define MAX_FREQ_TREBLE 3900.00
#define MAX_FREQ_DEF 3000.00
#define MIN_GAIN -20
#define MAX_GAIN 20
#define MAX_LOG10_Q 1.0
#define MIN_LOG10_Q -1.0
// DFT parameters
#define IMP_AMP 2000.0 // amplitude of impulse
#define NIMP 50 // number of samples in impulse response
#define F_STEP_DFT 10.0 // frequency steps to sample spectrum
#define F_MAG_N (int)(MAX_F_HZ/F_STEP_DFT) // number of frequency steps
extern struct freedv *g_pfreedv;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class FilterDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
FilterDlg::FilterDlg(wxWindow* parent, bool running, bool *newMicInFilter, bool *newSpkOutFilter,
wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
{
m_running = running;
m_newMicInFilter = newMicInFilter;
m_newSpkOutFilter = newSpkOutFilter;
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer30;
bSizer30 = new wxBoxSizer(wxVERTICAL);
// LPC Post Filter --------------------------------------------------------
wxStaticBoxSizer* lpcpfs = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("LPC Post Filter")), wxHORIZONTAL);
wxBoxSizer* left = new wxBoxSizer(wxVERTICAL);
m_codec2LPCPostFilterEnable = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition,wxDefaultSize, wxCHK_2STATE);
left->Add(m_codec2LPCPostFilterEnable);
m_codec2LPCPostFilterBassBoost = new wxCheckBox(this, wxID_ANY, _("0-1 kHz 3dB Boost"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
left->Add(m_codec2LPCPostFilterBassBoost);
lpcpfs->Add(left, 0, wxALL, 5);
newLPCPFControl(&m_codec2LPCPostFilterBeta, &m_staticTextBeta, lpcpfs, "Beta");
newLPCPFControl(&m_codec2LPCPostFilterGamma, &m_staticTextGamma, lpcpfs, "Gamma");
m_LPCPostFilterDefault = new wxButton(this, wxID_ANY, wxT("Default"));
lpcpfs->Add(m_LPCPostFilterDefault, 0, wxALL|wxALIGN_CENTRE_HORIZONTAL|wxALIGN_CENTRE_VERTICAL, 5);
bSizer30->Add(lpcpfs, 0, wxALL, 0);
// Speex pre-processor --------------------------------------------------
wxStaticBoxSizer* sbSizer_speexpp;
wxStaticBox *sb_speexpp = new wxStaticBox(this, wxID_ANY, _("Speex Mic Audio Pre-Processor"));
sbSizer_speexpp = new wxStaticBoxSizer(sb_speexpp, wxVERTICAL);
m_ckboxSpeexpp = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sb_speexpp->SetToolTip(_("Enable noise supression, dereverberation, AGC of mic signal"));
sbSizer_speexpp->Add(m_ckboxSpeexpp, wxALIGN_LEFT, 2);
bSizer30->Add(sbSizer_speexpp, 0, wxALL, 0);
// EQ Filters -----------------------------------------------------------
wxStaticBoxSizer* eqMicInSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Mic In Equaliser")), wxVERTICAL);
wxBoxSizer* eqMicInSizer1 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* eqMicInSizer2 = new wxBoxSizer(wxHORIZONTAL);
m_MicInBass = newEQ(eqMicInSizer1, "Bass" , MAX_FREQ_BASS, disableQ);
m_MicInTreble = newEQ(eqMicInSizer1, "Treble", MAX_FREQ_TREBLE, disableQ);
eqMicInSizer->Add(eqMicInSizer1);
m_MicInEnable = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition,wxDefaultSize, wxCHK_2STATE);
eqMicInSizer2->Add(m_MicInEnable,0,wxALIGN_CENTRE_VERTICAL|wxRIGHT,10);
m_MicInMid = newEQ(eqMicInSizer2, "Mid" , MAX_FREQ_DEF, enableQ);
m_MicInDefault = new wxButton(this, wxID_ANY, wxT("Default"));
eqMicInSizer2->Add(m_MicInDefault,0,wxALIGN_CENTRE_VERTICAL|wxLEFT,20);
eqMicInSizer->Add(eqMicInSizer2);
wxStaticBoxSizer* eqSpkOutSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Speaker Out Equaliser")), wxVERTICAL);
wxBoxSizer* eqSpkOutSizer1 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* eqSpkOutSizer2 = new wxBoxSizer(wxHORIZONTAL);
m_SpkOutBass = newEQ(eqSpkOutSizer1, "Bass" , MAX_FREQ_BASS, disableQ);
m_SpkOutTreble = newEQ(eqSpkOutSizer1, "Treble", MAX_FREQ_TREBLE, disableQ);
eqSpkOutSizer->Add(eqSpkOutSizer1);
m_SpkOutEnable = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition,wxDefaultSize, wxCHK_2STATE);
eqSpkOutSizer2->Add(m_SpkOutEnable,0,wxALIGN_CENTRE_VERTICAL|wxRIGHT,10);
m_SpkOutMid = newEQ(eqSpkOutSizer2, "Mid" , MAX_FREQ_DEF, enableQ);
m_SpkOutDefault = new wxButton(this, wxID_ANY, wxT("Default"));
eqSpkOutSizer2->Add(m_SpkOutDefault,0,wxALIGN_CENTRE_VERTICAL|wxLEFT,20);
eqSpkOutSizer->Add(eqSpkOutSizer2);
bSizer30->Add(eqMicInSizer, 0, wxALL, 0);
bSizer30->Add(eqSpkOutSizer, 0, wxALL, 0);
// Storgage for spectrum magnitude plots ------------------------------------
m_MicInMagdB = new float[F_MAG_N];
for(int i=0; i<F_MAG_N; i++)
m_MicInMagdB[i] = 0.0;
m_SpkOutMagdB = new float[F_MAG_N];
for(int i=0; i<F_MAG_N; i++)
m_SpkOutMagdB[i] = 0.0;
// Spectrum Plots -----------------------------------------------------------
long nb_style = wxAUI_NB_BOTTOM | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS;
m_auiNotebook = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(-1,200), nb_style);
m_auiNotebook->SetFont(wxFont(8, 70, 90, 90, false, wxEmptyString));
bSizer30->Add(m_auiNotebook, 0, wxEXPAND|wxALL, 3);
m_MicInFreqRespPlot = new PlotSpectrum((wxFrame*) m_auiNotebook, m_MicInMagdB, F_MAG_N, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
m_auiNotebook->AddPage(m_MicInFreqRespPlot, _("Microphone In Equaliser"));
m_SpkOutFreqRespPlot = new PlotSpectrum((wxFrame*)m_auiNotebook, m_SpkOutMagdB, F_MAG_N, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
m_auiNotebook->AddPage(m_SpkOutFreqRespPlot, _("Speaker Out Equaliser"));
// OK - Cancel buttons at the bottom --------------------------
wxBoxSizer* bSizer31 = new wxBoxSizer(wxHORIZONTAL);
m_sdbSizer5OK = new wxButton(this, wxID_OK);
bSizer31->Add(m_sdbSizer5OK, 0, wxALL, 2);
m_sdbSizer5Cancel = new wxButton(this, wxID_CANCEL);
bSizer31->Add(m_sdbSizer5Cancel, 0, wxALL, 2);
bSizer30->Add(bSizer31, 0, wxALIGN_RIGHT|wxALL, 0);
this->SetSizer(bSizer30);
this->Layout();
this->Centre(wxBOTH);
// Connect Events -------------------------------------------------------
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(FilterDlg::OnInitDialog));
m_codec2LPCPostFilterEnable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnEnable), NULL, this);
m_codec2LPCPostFilterBassBoost->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnBassBoost), NULL, this);
m_codec2LPCPostFilterBeta->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnBetaScroll), NULL, this);
m_codec2LPCPostFilterGamma->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnGammaScroll), NULL, this);
m_LPCPostFilterDefault->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnLPCPostFilterDefault), NULL, this);
m_ckboxSpeexpp->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnSpeexppEnable), NULL, this);
m_MicInBass.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInBassFreqScroll), NULL, this);
m_MicInBass.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInBassGainScroll), NULL, this);
m_MicInTreble.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInTrebleFreqScroll), NULL, this);
m_MicInTreble.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInTrebleGainScroll), NULL, this);
m_MicInMid.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidFreqScroll), NULL, this);
m_MicInMid.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidGainScroll), NULL, this);
m_MicInMid.sliderQ->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidQScroll), NULL, this);
m_MicInEnable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnMicInEnable), NULL, this);
m_MicInDefault->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnMicInDefault), NULL, this);
m_SpkOutBass.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutBassFreqScroll), NULL, this);
m_SpkOutBass.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutBassGainScroll), NULL, this);
m_SpkOutTreble.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutTrebleFreqScroll), NULL, this);
m_SpkOutTreble.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutTrebleGainScroll), NULL, this);
m_SpkOutMid.sliderFreq->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidFreqScroll), NULL, this);
m_SpkOutMid.sliderGain->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidGainScroll), NULL, this);
m_SpkOutMid.sliderQ->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidQScroll), NULL, this);
m_SpkOutEnable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnSpkOutEnable), NULL, this);
m_SpkOutDefault->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnSpkOutDefault), NULL, this);
m_sdbSizer5Cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnCancel), NULL, this);
m_sdbSizer5OK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnOK), NULL, this);
}
//-------------------------------------------------------------------------
// ~FilterDlg()
//-------------------------------------------------------------------------
FilterDlg::~FilterDlg()
{
delete m_MicInMagdB;
delete m_SpkOutMagdB;
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(FilterDlg::OnInitDialog));
m_codec2LPCPostFilterEnable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnEnable), NULL, this);
m_codec2LPCPostFilterBassBoost->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnBassBoost), NULL, this);
m_codec2LPCPostFilterBeta->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnBetaScroll), NULL, this);
m_codec2LPCPostFilterGamma->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnGammaScroll), NULL, this);
m_LPCPostFilterDefault->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnLPCPostFilterDefault), NULL, this);
m_MicInBass.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInBassFreqScroll), NULL, this);
m_MicInBass.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInBassGainScroll), NULL, this);
m_MicInTreble.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInTrebleFreqScroll), NULL, this);
m_MicInTreble.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInTrebleGainScroll), NULL, this);
m_MicInMid.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidFreqScroll), NULL, this);
m_MicInMid.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidGainScroll), NULL, this);
m_MicInMid.sliderQ->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnMicInMidQScroll), NULL, this);
m_MicInEnable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnMicInEnable), NULL, this);
m_MicInDefault->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnMicInDefault), NULL, this);
m_SpkOutBass.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutBassFreqScroll), NULL, this);
m_SpkOutBass.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutBassGainScroll), NULL, this);
m_SpkOutTreble.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutTrebleFreqScroll), NULL, this);
m_SpkOutTreble.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutTrebleGainScroll), NULL, this);
m_SpkOutMid.sliderFreq->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidFreqScroll), NULL, this);
m_SpkOutMid.sliderGain->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidGainScroll), NULL, this);
m_SpkOutMid.sliderQ->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(FilterDlg::OnSpkOutMidQScroll), NULL, this);
m_SpkOutEnable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(FilterDlg::OnSpkOutEnable), NULL, this);
m_SpkOutDefault->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnSpkOutDefault), NULL, this);
m_sdbSizer5Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnCancel), NULL, this);
m_sdbSizer5OK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnOK), NULL, this);
}
void FilterDlg::newLPCPFControl(wxSlider **slider, wxStaticText **stValue, wxSizer *s, wxString controlName)
{
wxBoxSizer *bs = new wxBoxSizer(wxHORIZONTAL);
wxStaticText* st = new wxStaticText(this, wxID_ANY, controlName, wxDefaultPosition, wxSize(70,-1), wxALIGN_RIGHT);
bs->Add(st, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 2);
*slider = new wxSlider(this, wxID_ANY, 0, 0, SLIDER_MAX, wxDefaultPosition, wxSize(SLIDER_LENGTH,wxDefaultCoord));
bs->Add(*slider, 1, wxALIGN_CENTER_VERTICAL|wxALL, 2);
*stValue = new wxStaticText(this, wxID_ANY, wxT("0.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
bs->Add(*stValue, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 2);
s->Add(bs, 0);
}
void FilterDlg::newEQControl(wxSlider** slider, wxStaticText** value, wxStaticBoxSizer *bs, wxString controlName)
{
wxStaticText* label = new wxStaticText(this, wxID_ANY, controlName, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
bs->Add(label, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 0);
*slider = new wxSlider(this, wxID_ANY, 0, 0, SLIDER_MAX, wxDefaultPosition, wxSize(SLIDER_LENGTH,wxDefaultCoord));
bs->Add(*slider, 1, wxALIGN_CENTER_VERTICAL|wxALL, 0);
*value = new wxStaticText(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(40,-1), wxALIGN_LEFT);
bs->Add(*value, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT, 5);
}
EQ FilterDlg::newEQ(wxSizer *bs, wxString eqName, float maxFreqHz, bool enableQ)
{
EQ eq;
wxStaticBoxSizer *bsEQ = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, eqName), wxHORIZONTAL);
newEQControl(&eq.sliderFreq, &eq.valueFreq, bsEQ, "Freq");
eq.maxFreqHz = maxFreqHz;
eq.sliderFreqId = eq.sliderFreq->GetId();
newEQControl(&eq.sliderGain, &eq.valueGain, bsEQ, "Gain");
if (enableQ)
newEQControl(&eq.sliderQ, &eq.valueQ, bsEQ, "Q");
else
eq.sliderQ = NULL;
bs->Add(bsEQ);
return eq;
}
//-------------------------------------------------------------------------
// ExchangeData()
//-------------------------------------------------------------------------
void FilterDlg::ExchangeData(int inout, bool storePersistent)
{
wxConfigBase *pConfig = wxConfigBase::Get();
if(inout == EXCHANGE_DATA_IN)
{
// LPC Post filter
m_codec2LPCPostFilterEnable->SetValue(wxGetApp().m_codec2LPCPostFilterEnable);
m_codec2LPCPostFilterBassBoost->SetValue(wxGetApp().m_codec2LPCPostFilterBassBoost);
m_beta = wxGetApp().m_codec2LPCPostFilterBeta; setBeta();
m_gamma = wxGetApp().m_codec2LPCPostFilterGamma; setGamma();
// Speex Pre-Processor
m_ckboxSpeexpp->SetValue(wxGetApp().m_speexpp_enable);
// Mic In Equaliser
m_MicInBass.freqHz = wxGetApp().m_MicInBassFreqHz;
m_MicInBass.freqHz = limit(m_MicInBass.freqHz, 1.0, MAX_FREQ_BASS);
setFreq(&m_MicInBass);
m_MicInBass.gaindB = wxGetApp().m_MicInBassGaindB;
m_MicInBass.gaindB = limit(m_MicInBass.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_MicInBass);
m_MicInTreble.freqHz = wxGetApp().m_MicInTrebleFreqHz;
m_MicInTreble.freqHz = limit(m_MicInTreble.freqHz, 1.0, MAX_FREQ_TREBLE);
setFreq(&m_MicInTreble);
m_MicInTreble.gaindB = wxGetApp().m_MicInTrebleGaindB;
m_MicInTreble.gaindB = limit(m_MicInTreble.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_MicInTreble);
m_MicInMid.freqHz = wxGetApp().m_MicInMidFreqHz;
m_MicInMid.freqHz = limit(m_MicInMid.freqHz, 1.0, MAX_FREQ_TREBLE);
setFreq(&m_MicInMid);
m_MicInMid.gaindB = wxGetApp().m_MicInMidGaindB;
m_MicInMid.gaindB = limit(m_MicInMid.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_MicInMid);
m_MicInMid.Q = wxGetApp().m_MicInMidQ;
m_MicInMid.Q = limit(m_MicInMid.Q, pow(10.0,MIN_LOG10_Q), pow(10.0, MAX_LOG10_Q));
setQ(&m_MicInMid);
m_MicInEnable->SetValue(wxGetApp().m_MicInEQEnable);
plotMicInFilterSpectrum();
// Spk Out Equaliser
m_SpkOutBass.freqHz = wxGetApp().m_SpkOutBassFreqHz;
m_SpkOutBass.freqHz = limit(m_SpkOutBass.freqHz, 1.0, MAX_FREQ_BASS);
setFreq(&m_SpkOutBass);
m_SpkOutBass.gaindB = wxGetApp().m_SpkOutBassGaindB;
m_SpkOutBass.gaindB = limit(m_SpkOutBass.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_SpkOutBass);
m_SpkOutTreble.freqHz = wxGetApp().m_SpkOutTrebleFreqHz;
m_SpkOutTreble.freqHz = limit(m_SpkOutTreble.freqHz, 1.0, MAX_FREQ_TREBLE);
setFreq(&m_SpkOutTreble);
m_SpkOutTreble.gaindB = wxGetApp().m_SpkOutTrebleGaindB;
m_SpkOutTreble.gaindB = limit(m_SpkOutTreble.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_SpkOutTreble);
m_SpkOutMid.freqHz = wxGetApp().m_SpkOutMidFreqHz;
m_SpkOutMid.freqHz = limit(m_SpkOutMid.freqHz, 1.0, MAX_FREQ_TREBLE);
setFreq(&m_SpkOutMid);
m_SpkOutMid.gaindB = wxGetApp().m_SpkOutMidGaindB;
m_SpkOutMid.gaindB = limit(m_SpkOutMid.gaindB, MIN_GAIN, MAX_GAIN);
setGain(&m_SpkOutMid);
m_SpkOutMid.Q = wxGetApp().m_SpkOutMidQ;
m_SpkOutMid.Q = limit(m_SpkOutMid.Q, pow(10.0,MIN_LOG10_Q), pow(10.0, MAX_LOG10_Q));
setQ(&m_SpkOutMid);
m_SpkOutEnable->SetValue(wxGetApp().m_SpkOutEQEnable);
plotSpkOutFilterSpectrum();
}
if(inout == EXCHANGE_DATA_OUT)
{
// LPC Post filter
wxGetApp().m_codec2LPCPostFilterEnable = m_codec2LPCPostFilterEnable->GetValue();
wxGetApp().m_codec2LPCPostFilterBassBoost = m_codec2LPCPostFilterBassBoost->GetValue();
wxGetApp().m_codec2LPCPostFilterBeta = m_beta;
wxGetApp().m_codec2LPCPostFilterGamma = m_gamma;
// Speex Pre-Processor
wxGetApp().m_speexpp_enable = m_ckboxSpeexpp->GetValue();
// Mic In Equaliser
wxGetApp().m_MicInBassFreqHz = m_MicInBass.freqHz;
wxGetApp().m_MicInBassGaindB = m_MicInBass.gaindB;
wxGetApp().m_MicInTrebleFreqHz = m_MicInTreble.freqHz;
wxGetApp().m_MicInTrebleGaindB = m_MicInTreble.gaindB;
wxGetApp().m_MicInMidFreqHz = m_MicInMid.freqHz;
wxGetApp().m_MicInMidGaindB = m_MicInMid.gaindB;
wxGetApp().m_MicInMidQ = m_MicInMid.Q;
// Spk Out Equaliser
wxGetApp().m_SpkOutBassFreqHz = m_SpkOutBass.freqHz;
wxGetApp().m_SpkOutBassGaindB = m_SpkOutBass.gaindB;
wxGetApp().m_SpkOutTrebleFreqHz = m_SpkOutTreble.freqHz;
wxGetApp().m_SpkOutTrebleGaindB = m_SpkOutTreble.gaindB;
wxGetApp().m_SpkOutMidFreqHz = m_SpkOutMid.freqHz;
wxGetApp().m_SpkOutMidGaindB = m_SpkOutMid.gaindB;
wxGetApp().m_SpkOutMidQ = m_SpkOutMid.Q;
if (storePersistent) {
pConfig->Write(wxT("/Filter/codec2LPCPostFilterEnable"), wxGetApp().m_codec2LPCPostFilterEnable);
pConfig->Write(wxT("/Filter/codec2LPCPostFilterBassBoost"), wxGetApp().m_codec2LPCPostFilterBassBoost);
pConfig->Write(wxT("/Filter/codec2LPCPostFilterBeta"), (int)(m_beta*100.0));
pConfig->Write(wxT("/Filter/codec2LPCPostFilterGamma"), (int)(m_gamma*100.0));
pConfig->Write(wxT("/Filter/speexpp_enable"), wxGetApp().m_speexpp_enable);
pConfig->Write(wxT("/Filter/MicInBassFreqHz"), (int)m_MicInBass.freqHz);
pConfig->Write(wxT("/Filter/MicInBassGaindB"), (int)(10.0*m_MicInBass.gaindB));
pConfig->Write(wxT("/Filter/MicInTrebleFreqHz"), (int)m_MicInTreble.freqHz);
pConfig->Write(wxT("/Filter/MicInTrebleGaindB"), (int)(10.0*m_MicInTreble.gaindB));
pConfig->Write(wxT("/Filter/MicInMidFreqHz"), (int)m_MicInMid.freqHz);
pConfig->Write(wxT("/Filter/MicInMidGaindB"), (int)(10.0*m_MicInMid.gaindB));
pConfig->Write(wxT("/Filter/MicInMidQ"), (int)(100.0*m_MicInMid.Q));
pConfig->Write(wxT("/Filter/SpkOutBassFreqHz"), (int)m_SpkOutBass.freqHz);
pConfig->Write(wxT("/Filter/SpkOutBassGaindB"), (int)(10.0*m_SpkOutBass.gaindB));
pConfig->Write(wxT("/Filter/SpkOutTrebleFreqHz"), (int)m_SpkOutTreble.freqHz);
pConfig->Write(wxT("/Filter/SpkOutTrebleGaindB"), (int)(10.0*m_SpkOutTreble.gaindB));
pConfig->Write(wxT("/Filter/SpkOutMidQ"), (int)(100.0*m_SpkOutMid.Q));
pConfig->Write(wxT("/Filter/SpkOutMidFreqHz"), (int)m_SpkOutMid.freqHz);
pConfig->Write(wxT("/Filter/SpkOutMidGaindB"), (int)(10.0*m_SpkOutMid.gaindB));
pConfig->Flush();
}
}
delete wxConfigBase::Set((wxConfigBase *) NULL);
}
float FilterDlg::limit(float value, float min, float max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
//-------------------------------------------------------------------------
// OnCancel()
//-------------------------------------------------------------------------
void FilterDlg::OnCancel(wxCommandEvent& event)
{
this->EndModal(wxID_CANCEL);
}
//-------------------------------------------------------------------------
// OnDefault()
//-------------------------------------------------------------------------
void FilterDlg::OnLPCPostFilterDefault(wxCommandEvent& event)
{
m_beta = CODEC2_LPC_PF_BETA; setBeta();
m_gamma = CODEC2_LPC_PF_GAMMA; setGamma();
m_codec2LPCPostFilterEnable->SetValue(true);
m_codec2LPCPostFilterBassBoost->SetValue(true);
}
void FilterDlg::OnMicInDefault(wxCommandEvent& event)
{
m_MicInBass.freqHz = 100.0;
m_MicInBass.gaindB = 0.0;
setFreq(&m_MicInBass); setGain(&m_MicInBass);
m_MicInTreble.freqHz = 3000.0;
m_MicInTreble.gaindB = 0.0;
setFreq(&m_MicInTreble); setGain(&m_MicInTreble);
m_MicInMid.freqHz = 1500.0;
m_MicInMid.gaindB = 0.0;
m_MicInMid.Q = 1.0;
setFreq(&m_MicInMid); setGain(&m_MicInMid); setQ(&m_MicInMid);
plotMicInFilterSpectrum();
}
void FilterDlg::OnSpkOutDefault(wxCommandEvent& event)
{
m_SpkOutBass.freqHz = 100.0;
m_SpkOutBass.gaindB = 0.0;
setFreq(&m_SpkOutBass); setGain(&m_SpkOutBass);
m_SpkOutTreble.freqHz = 3000.0;
m_SpkOutTreble.gaindB = 0.0;
setFreq(&m_SpkOutTreble); setGain(&m_SpkOutTreble);
m_SpkOutMid.freqHz = 1500.0;
m_SpkOutMid.gaindB = 0.0;
m_SpkOutMid.Q = 1.0;
setFreq(&m_SpkOutMid); setGain(&m_SpkOutMid); setQ(&m_SpkOutMid);
plotSpkOutFilterSpectrum();
}
//-------------------------------------------------------------------------
// OnOK()
//-------------------------------------------------------------------------
void FilterDlg::OnOK(wxCommandEvent& event)
{
//printf("FilterDlg::OnOK\n");
ExchangeData(EXCHANGE_DATA_OUT, true);
this->EndModal(wxID_OK);
}
//-------------------------------------------------------------------------
// OnClose()
//-------------------------------------------------------------------------
void FilterDlg::OnClose(wxCloseEvent& event)
{
this->EndModal(wxID_OK);
}
//-------------------------------------------------------------------------
// OnInitDialog()
//-------------------------------------------------------------------------
void FilterDlg::OnInitDialog(wxInitDialogEvent& event)
{
//printf("FilterDlg::OnInitDialog\n");
ExchangeData(EXCHANGE_DATA_IN, false);
//printf("m_beta: %f\n", m_beta);
}
void FilterDlg::setBeta(void) {
wxString buf;
buf.Printf(wxT("%3.2f"), m_beta);
m_staticTextBeta->SetLabel(buf);
int slider = (int)(m_beta*SLIDER_MAX + 0.5);
m_codec2LPCPostFilterBeta->SetValue(slider);
}
void FilterDlg::setCodec2(void) {
if (m_running) {
assert(g_pfreedv->codec2 != NULL);
codec2_set_lpc_post_filter(g_pfreedv->codec2,
m_codec2LPCPostFilterEnable->GetValue(),
m_codec2LPCPostFilterBassBoost->GetValue(),
m_beta, m_gamma);
}
}
void FilterDlg::setGamma(void) {
wxString buf;
buf.Printf(wxT("%3.2f"), m_gamma);
m_staticTextGamma->SetLabel(buf);
int slider = (int)(m_gamma*SLIDER_MAX + 0.5);
m_codec2LPCPostFilterGamma->SetValue(slider);
}
void FilterDlg::OnEnable(wxScrollEvent& event) {
setCodec2();
}
void FilterDlg::OnBassBoost(wxScrollEvent& event) {
setCodec2();
}
void FilterDlg::OnBetaScroll(wxScrollEvent& event) {
m_beta = (float)m_codec2LPCPostFilterBeta->GetValue()/SLIDER_MAX;
setBeta();
setCodec2();
}
void FilterDlg::OnGammaScroll(wxScrollEvent& event) {
m_gamma = (float)m_codec2LPCPostFilterGamma->GetValue()/SLIDER_MAX;
setGamma();
setCodec2();
}
// immediately change enable flags rather using ExchangeData() so we can switch on and off at run time
void FilterDlg::OnSpeexppEnable(wxScrollEvent& event) {
wxGetApp().m_speexpp_enable = m_ckboxSpeexpp->GetValue();
}
void FilterDlg::OnMicInEnable(wxScrollEvent& event) {
wxGetApp().m_MicInEQEnable = m_MicInEnable->GetValue();
}
void FilterDlg::OnSpkOutEnable(wxScrollEvent& event) {
wxGetApp().m_SpkOutEQEnable = m_SpkOutEnable->GetValue();
//printf("wxGetApp().m_SpkOutEQEnable: %d\n", wxGetApp().m_SpkOutEQEnable);
}
void FilterDlg::setFreq(EQ *eq)
{
wxString buf;
buf.Printf(wxT("%3.0f"), eq->freqHz);
eq->valueFreq->SetLabel(buf);
int slider = (int)((eq->freqHz/eq->maxFreqHz)*SLIDER_MAX + 0.5);
eq->sliderFreq->SetValue(slider);
}
void FilterDlg::sliderToFreq(EQ *eq, bool micIn)
{
eq->freqHz = ((float)eq->sliderFreq->GetValue()/SLIDER_MAX)*eq->maxFreqHz;
if (eq->freqHz < 1.0) eq->freqHz = 1.0; // sox doesn't like 0 Hz;
setFreq(eq);
if (micIn) {
plotMicInFilterSpectrum();
adjRunTimeMicInFilter();
}
else {
plotSpkOutFilterSpectrum();
adjRunTimeSpkOutFilter();
}
}
void FilterDlg::setGain(EQ *eq)
{
wxString buf;
buf.Printf(wxT("%3.1f"), eq->gaindB);
eq->valueGain->SetLabel(buf);
int slider = (int)(((eq->gaindB-MIN_GAIN)/(MAX_GAIN-MIN_GAIN))*SLIDER_MAX + 0.5);
eq->sliderGain->SetValue(slider);
}
void FilterDlg::sliderToGain(EQ *eq, bool micIn)
{
float range = MAX_GAIN-MIN_GAIN;
eq->gaindB = MIN_GAIN + range*((float)eq->sliderGain->GetValue()/SLIDER_MAX);
//printf("gaindB: %f\n", eq->gaindB);
setGain(eq);
if (micIn) {
plotMicInFilterSpectrum();
adjRunTimeMicInFilter();
}
else {
plotSpkOutFilterSpectrum();
adjRunTimeSpkOutFilter();
}
}
void FilterDlg::setQ(EQ *eq)
{
wxString buf;
buf.Printf(wxT("%2.1f"), eq->Q);
eq->valueQ->SetLabel(buf);
float log10_range = MAX_LOG10_Q - MIN_LOG10_Q;
int slider = (int)(((log10(eq->Q+1E-6)-MIN_LOG10_Q)/log10_range)*SLIDER_MAX + 0.5);
eq->sliderQ->SetValue(slider);
}
void FilterDlg::sliderToQ(EQ *eq, bool micIn)
{
float log10_range = MAX_LOG10_Q - MIN_LOG10_Q;
float sliderNorm = (float)eq->sliderQ->GetValue()/SLIDER_MAX;
float log10Q = MIN_LOG10_Q + sliderNorm*(log10_range);
eq->Q = pow(10.0, log10Q);
//printf("log10Q: %f eq->Q: %f\n", log10Q, eq->Q);
setQ(eq);
if (micIn) {
plotMicInFilterSpectrum();
adjRunTimeMicInFilter();
}
else {
plotSpkOutFilterSpectrum();
adjRunTimeSpkOutFilter();
}
}
void FilterDlg::plotMicInFilterSpectrum(void) {
plotFilterSpectrum(&m_MicInBass, &m_MicInMid, &m_MicInTreble, m_MicInFreqRespPlot, m_MicInMagdB);
}
void FilterDlg::plotSpkOutFilterSpectrum(void) {
plotFilterSpectrum(&m_SpkOutBass, &m_SpkOutMid, &m_SpkOutTreble, m_SpkOutFreqRespPlot, m_SpkOutMagdB);
}
void FilterDlg::adjRunTimeMicInFilter(void) {
// signal an adjustment in running filter coeffs
if (m_running) {
ExchangeData(EXCHANGE_DATA_OUT, false);
*m_newMicInFilter = true;
}
}
void FilterDlg::adjRunTimeSpkOutFilter(void) {
// signal an adjustment in running filter coeffs
if (m_running) {
ExchangeData(EXCHANGE_DATA_OUT, false);
*m_newSpkOutFilter = true;
}
}
void FilterDlg::plotFilterSpectrum(EQ *eqBass, EQ *eqMid, EQ *eqTreble, PlotSpectrum* freqRespPlot, float *magdB) {
char *argBass[10];
char *argTreble[10];
char *argMid[10];
char argstorage[10][80];
float magBass[F_MAG_N];
float magTreble[F_MAG_N];
float magMid[F_MAG_N];
int i;
for(i=0; i<10; i++) {
argBass[i] = &argstorage[i][0];
argTreble[i] = &argstorage[i][0];
argMid[i] = &argstorage[i][0];
}
sprintf(argBass[0], "bass");
sprintf(argBass[1], "%f", eqBass->gaindB+1E-6);
sprintf(argBass[2], "%f", eqBass->freqHz);
calcFilterSpectrum(magBass, 2, argBass);
sprintf(argTreble[0], "treble");
sprintf(argTreble[1], "%f", eqTreble->gaindB+1E-6);
sprintf(argTreble[2], "%f", eqTreble->freqHz);
calcFilterSpectrum(magTreble, 2, argTreble);
sprintf(argTreble[0], "equalizer");
sprintf(argTreble[1], "%f", eqMid->freqHz);
sprintf(argTreble[2], "%f", eqMid->Q);
sprintf(argTreble[3], "%f", eqMid->gaindB+1E-6);
calcFilterSpectrum(magMid, 3, argMid);
for(i=0; i<F_MAG_N; i++)
magdB[i] = magBass[i] + magMid[i] + magTreble[i];
freqRespPlot->m_newdata = true;
freqRespPlot->Refresh();
}
void FilterDlg::calcFilterSpectrum(float magdB[], int argc, char *argv[]) {
void *sbq;
short in[NIMP];
short out[NIMP];
COMP X[F_MAG_N];
float f, w;
int i, k;
// find impulse response -----------------------------------
for(i=0; i<NIMP; i++)
in[i] = 0;
in[0] = IMP_AMP;
//printf("argv[0]: %s argv[1]: %s\n", argv[0], argv[1]);
sbq = sox_biquad_create(argc, (const char **)argv);
sox_biquad_filter(sbq, out, in, NIMP);
//for(i=0; i<NIMP; i++)
// printf("%d\n", out[i]);
sox_biquad_destroy(sbq);
//for(i=0; i<NIMP; i++)
// out[i] = 0.0;
//out[0] = IMP_AMP;
// calculate discrete time continous frequency Fourer transform
// doing this from first principles rather than FFT for no good reason
for(f=0,i=0; f<MAX_F_HZ; f+=F_STEP_DFT,i++) {
w = M_PI*f/(FS/2);
X[i].real = 0.0; X[i].imag = 0.0;
for(k=0; k<NIMP; k++) {
X[i].real += ((float)out[k]/IMP_AMP) * cos(w*k);
X[i].imag -= ((float)out[k]/IMP_AMP) * sin(w*k);
}
magdB[i] = 10.0*log10(X[i].real* X[i].real + X[i].imag*X[i].imag + 1E-12);
//printf("f: %f X[%d] = %f %f magdB = %f\n", f, i, X[i].real, X[i].imag, magdB[i]);
}
}

166
src/dlg_filter.h 100644
View File

@ -0,0 +1,166 @@
//==========================================================================
// Name: dlg_filter.h
// Purpose: Dialog for controlling Codec audio filtering
// Created: Nov 25 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FILTER_DIALOG__
#define __FILTER_DIALOG__
#include "fdmdv2_main.h"
enum {disableQ = false, enableQ = true};
typedef struct {
wxSlider *sliderFreq;
wxStaticText *valueFreq;
wxSlider *sliderGain;
wxStaticText *valueGain;
wxSlider *sliderQ;
wxStaticText *valueQ;
int sliderFreqId;
int sliderGainId;
int sliderQId;
float freqHz;
float gaindB;
float Q;
float maxFreqHz;
} EQ;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class FilterDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class FilterDlg : public wxDialog
{
public:
FilterDlg( wxWindow* parent, bool running, bool *newMicInFilter, bool *newSpkOutFilter,
wxWindowID id = wxID_ANY, const wxString& title = _("Filter"),
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 800, 630 ),
long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~FilterDlg();
void ExchangeData(int inout, bool storePersistent);
protected:
// Handlers for events.
void OnCancel(wxCommandEvent& event);
void OnOK(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
void OnInitDialog(wxInitDialogEvent& event);
void OnLPCPostFilterDefault(wxCommandEvent& event);
void OnBetaScroll(wxScrollEvent& event);
void OnGammaScroll(wxScrollEvent& event);
void OnEnable(wxScrollEvent& event);
void OnBassBoost(wxScrollEvent& event);
void OnSpeexppEnable(wxScrollEvent& event);
void OnMicInBassFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_MicInBass, true); }
void OnMicInBassGainScroll(wxScrollEvent& event) { sliderToGain(&m_MicInBass, true); }
void OnMicInTrebleFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_MicInTreble, true); }
void OnMicInTrebleGainScroll(wxScrollEvent& event) { sliderToGain(&m_MicInTreble, true); }
void OnMicInMidFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_MicInMid, true); }
void OnMicInMidGainScroll(wxScrollEvent& event) { sliderToGain(&m_MicInMid, true); }
void OnMicInMidQScroll(wxScrollEvent& event) { sliderToQ(&m_MicInMid, true); }
void OnMicInEnable(wxScrollEvent& event);
void OnMicInDefault(wxCommandEvent& event);
void OnSpkOutBassFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_SpkOutBass, false); }
void OnSpkOutBassGainScroll(wxScrollEvent& event) { sliderToGain(&m_SpkOutBass, false); }
void OnSpkOutTrebleFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_SpkOutTreble, false); }
void OnSpkOutTrebleGainScroll(wxScrollEvent& event) { sliderToGain(&m_SpkOutTreble, false); }
void OnSpkOutMidFreqScroll(wxScrollEvent& event) { sliderToFreq(&m_SpkOutMid, false); }
void OnSpkOutMidGainScroll(wxScrollEvent& event) { sliderToGain(&m_SpkOutMid, false); }
void OnSpkOutMidQScroll(wxScrollEvent& event) { sliderToQ(&m_SpkOutMid, false); }
void OnSpkOutEnable(wxScrollEvent& event);
void OnSpkOutDefault(wxCommandEvent& event);
wxStaticText* m_staticText8;
wxCheckBox* m_codec2LPCPostFilterEnable;
wxStaticText* m_staticText9;
wxCheckBox* m_codec2LPCPostFilterBassBoost;
wxStaticText* m_staticText91;
wxSlider* m_codec2LPCPostFilterBeta;
wxStaticText* m_staticTextBeta;
wxStaticText* m_staticText911;
wxSlider* m_codec2LPCPostFilterGamma;
wxStaticText* m_staticTextGamma;
wxButton* m_LPCPostFilterDefault;
wxCheckBox* m_ckboxSpeexpp;
wxStdDialogButtonSizer* m_sdbSizer5;
wxButton* m_sdbSizer5OK;
wxButton* m_sdbSizer5Cancel;
PlotSpectrum* m_MicInFreqRespPlot;
PlotSpectrum* m_SpkOutFreqRespPlot;
wxCheckBox* m_MicInEnable;
wxButton* m_MicInDefault;
wxCheckBox* m_SpkOutEnable;
wxButton* m_SpkOutDefault;
float *m_MicInMagdB;
float *m_SpkOutMagdB;
private:
bool m_running;
float m_beta;
float m_gamma;
void setBeta(void); // sets slider and static text from m_beta
void setGamma(void); // sets slider and static text from m_gamma
void setCodec2(void);
void newEQControl(wxSlider** slider, wxStaticText** value, wxStaticBoxSizer *bs, wxString controlName);
EQ newEQ(wxSizer *bs, wxString eqName, float maxFreqHz, bool enableQ);
void newLPCPFControl(wxSlider **slider, wxStaticText **stValue, wxSizer *sbs, wxString controlName);
wxAuiNotebook *m_auiNotebook;
void setFreq(EQ *eq);
void setGain(EQ *eq);
void setQ(EQ *eq);
void sliderToFreq(EQ *eq, bool micIn);
void sliderToGain(EQ *eq, bool micIn);
void sliderToQ(EQ *eq, bool micIn);
void plotFilterSpectrum(EQ *eqBass, EQ *eqMid, EQ* eqTreble, PlotSpectrum* freqRespPlot, float *magdB);
void calcFilterSpectrum(float magdB[], int arc, char *argv[]);
void plotMicInFilterSpectrum(void);
void plotSpkOutFilterSpectrum(void);
void adjRunTimeMicInFilter(void);
void adjRunTimeSpkOutFilter(void);
EQ m_MicInBass;
EQ m_MicInMid;
EQ m_MicInTreble;
EQ m_SpkOutBass;
EQ m_SpkOutMid;
EQ m_SpkOutTreble;
float limit(float value, float min, float max);
bool *m_newMicInFilter;
bool *m_newSpkOutFilter;
};
#endif // __FILTER_DIALOG__

363
src/dlg_options.cpp 100644
View File

@ -0,0 +1,363 @@
//==========================================================================
// Name: dlg_options.cpp
// Purpose: Dialog for controlling misc FreeDV options
// Date: May 24 2013
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include "dlg_options.h"
extern bool g_modal;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class OptionsDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer30;
bSizer30 = new wxBoxSizer(wxVERTICAL);
//------------------------------
// Test Frames check box
//------------------------------
wxStaticBoxSizer* sbSizer_testFrames;
wxStaticBox *sb_testFrames = new wxStaticBox(this, wxID_ANY, _("Test Frames"));
sbSizer_testFrames = new wxStaticBoxSizer(sb_testFrames, wxHORIZONTAL);
m_ckboxTestFrame = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
m_ckboxTestFrame->SetToolTip(_("Send frames of known bits instead of compressed voice"));
sbSizer_testFrames->Add(m_ckboxTestFrame, 0, wxALIGN_LEFT, 0);
m_ckboxChannelNoise = new wxCheckBox(this, wxID_ANY, _("Channel Noise"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
m_ckboxChannelNoise->SetToolTip(_("Add simulated AWGN channel noise to received signal"));
sbSizer_testFrames->Add(m_ckboxChannelNoise, 0, wxALIGN_LEFT, 0);
bSizer30->Add(sbSizer_testFrames,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// FreeDV 700 Options
//------------------------------
wxStaticBoxSizer* sbSizer_freedv700;
wxStaticBox *sb_freedv700 = new wxStaticBox(this, wxID_ANY, _("FreeDV 700 Clipping"));
sbSizer_freedv700 = new wxStaticBoxSizer(sb_freedv700, wxHORIZONTAL);
m_ckboxFreeDV700txClip = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
m_ckboxFreeDV700txClip->SetToolTip(_("Clip FreeDv 700 tx waveform to reduce Peak to Average Power Ratio (PAPR)"));
sbSizer_freedv700->Add(m_ckboxFreeDV700txClip, 0, wxALIGN_LEFT, 0);
bSizer30->Add(sbSizer_freedv700,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// Txt Msg Text Box
//------------------------------
wxStaticBoxSizer* sbSizer_callSign;
wxStaticBox *sb_textMsg = new wxStaticBox(this, wxID_ANY, _("Txt Msg"));
sbSizer_callSign = new wxStaticBoxSizer(sb_textMsg, wxVERTICAL);
m_txtCtrlCallSign = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
m_txtCtrlCallSign->SetToolTip(_("Txt Msg you can send along with Voice"));
sbSizer_callSign->Add(m_txtCtrlCallSign, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 3);
bSizer30->Add(sbSizer_callSign,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// Txt Encoding
//------------------------------
wxStaticBoxSizer* sbSizer_encoding = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Text Encoding")), wxHORIZONTAL);
#ifdef SHORT_VARICODE
m_rb_textEncoding1 = new wxRadioButton( this, wxID_ANY, wxT("Long varicode"), wxDefaultPosition, wxDefaultSize, 0);
m_rb_textEncoding1->SetValue(true);
sbSizer_encoding->Add(m_rb_textEncoding1, 0, wxALIGN_LEFT|wxALL, 1);
m_rb_textEncoding2 = new wxRadioButton( this, wxID_ANY, wxT("Short Varicode"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_encoding->Add(m_rb_textEncoding2, 0, wxALIGN_LEFT|wxALL, 1);
#endif
m_ckboxEnableChecksum = new wxCheckBox(this, wxID_ANY, _("Use Checksum on Rx"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sbSizer_encoding->Add(m_ckboxEnableChecksum, 0, wxALIGN_LEFT, 0);
bSizer30->Add(sbSizer_encoding,0, wxALL|wxEXPAND, 3);
//------------------------------
// Event processing
//------------------------------
wxStaticBoxSizer* sbSizer_events;
wxStaticBox *sb_events = new wxStaticBox(this, wxID_ANY, _("Event Processing"));
sbSizer_events = new wxStaticBoxSizer(sb_events, wxVERTICAL);
// event processing enable and spam timer
wxStaticBoxSizer* sbSizer_events_top;
wxStaticBox* sb_events1 = new wxStaticBox(this, wxID_ANY, _(""));
sbSizer_events_top = new wxStaticBoxSizer(sb_events1, wxHORIZONTAL);
m_ckbox_events = new wxCheckBox(this, wxID_ANY, _("Enable System Calls Syscall Spam Timer"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sb_events->SetToolTip(_("Enable processing of events and generation of system calls"));
sbSizer_events_top->Add(m_ckbox_events, 0, 0, 5);
m_txt_spam_timer = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(40,-1), 0, wxTextValidator(wxFILTER_DIGITS));
m_txt_spam_timer->SetToolTip(_("Many matching events can cause a flood of syscalls. Set minimum time (seconds) between syscalls for each event here"));
sbSizer_events_top->Add(m_txt_spam_timer, 0, 0, 5);
m_rb_spam_timer = new wxRadioButton( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
m_rb_spam_timer->SetForegroundColour( wxColour(0, 255, 0 ) );
sbSizer_events_top->Add(m_rb_spam_timer, 0, 0, 10);
sbSizer_events->Add(sbSizer_events_top, 0, 0, 5);
// list of regexps
wxStaticBoxSizer* sbSizer_regexp = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Regular Expressions to Process Events")), wxHORIZONTAL);
m_txt_events_regexp_match = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,100), wxTE_MULTILINE);
m_txt_events_regexp_match->SetToolTip(_("Enter regular expressions to match events"));
sbSizer_regexp->Add(m_txt_events_regexp_match, 1, wxEXPAND, 5);
m_txt_events_regexp_replace = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,100), wxTE_MULTILINE);
m_txt_events_regexp_replace->SetToolTip(_("Enter regular expressions to replace events"));
sbSizer_regexp->Add(m_txt_events_regexp_replace, 1, wxEXPAND, 5);
sbSizer_events->Add(sbSizer_regexp, 1, wxEXPAND, 5);
// log of events and responses
wxStaticBoxSizer* sbSizer_event_log = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Log of Events and Responses")), wxVERTICAL);
wxBoxSizer* bSizer33 = new wxBoxSizer(wxHORIZONTAL);
m_txt_events_in = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,50), wxTE_MULTILINE | wxTE_READONLY);
bSizer33->Add(m_txt_events_in, 1, wxEXPAND, 5);
m_txt_events_out = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,50), wxTE_MULTILINE | wxTE_READONLY);
bSizer33->Add(m_txt_events_out, 1, wxEXPAND, 5);
sbSizer_event_log->Add(bSizer33, 1, wxEXPAND, 5);
sbSizer_events->Add(sbSizer_event_log, 1, wxEXPAND, 5);
bSizer30->Add(sbSizer_events,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// UDP control port
//------------------------------
wxStaticBoxSizer* sbSizer_udp;
wxStaticBox* sb_udp = new wxStaticBox(this, wxID_ANY, _("UDP Control Port"));
sbSizer_udp = new wxStaticBoxSizer(sb_udp, wxHORIZONTAL);
m_ckbox_udp_enable = new wxCheckBox(this, wxID_ANY, _("Enable UDP Control Port UDP Port Number:"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sb_udp->SetToolTip(_("Enable control of FreeDV via UDP port"));
sbSizer_udp->Add(m_ckbox_udp_enable, 0, wxALIGN_CENTER_HORIZONTAL, 5);
m_txt_udp_port = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50,-1), 0, wxTextValidator(wxFILTER_DIGITS));
sbSizer_udp->Add(m_txt_udp_port, 0, wxALIGN_CENTER_HORIZONTAL, 5);
bSizer30->Add(sbSizer_udp,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// OK - Cancel - Apply Buttons
//------------------------------
wxBoxSizer* bSizer31 = new wxBoxSizer(wxHORIZONTAL);
m_sdbSizer5OK = new wxButton(this, wxID_OK);
bSizer31->Add(m_sdbSizer5OK, 0, wxALL, 2);
m_sdbSizer5Cancel = new wxButton(this, wxID_CANCEL);
bSizer31->Add(m_sdbSizer5Cancel, 0, wxALL, 2);
m_sdbSizer5Apply = new wxButton(this, wxID_APPLY);
bSizer31->Add(m_sdbSizer5Apply, 0, wxALL, 2);
bSizer30->Add(bSizer31, 0, wxALIGN_RIGHT|wxALL, 0);
this->SetSizer(bSizer30);
this->Layout();
this->Centre(wxBOTH);
// Connect Events -------------------------------------------------------
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(OptionsDlg::OnInitDialog));
m_sdbSizer5OK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnOK), NULL, this);
m_sdbSizer5Cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnCancel), NULL, this);
m_sdbSizer5Apply->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnApply), NULL, this);
m_ckboxFreeDV700txClip->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this);
event_in_serial = 0;
event_out_serial = 0;
}
//-------------------------------------------------------------------------
// ~OptionsDlg()
//-------------------------------------------------------------------------
OptionsDlg::~OptionsDlg()
{
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(OptionsDlg::OnInitDialog));
m_sdbSizer5OK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnOK), NULL, this);
m_sdbSizer5Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnCancel), NULL, this);
m_sdbSizer5Apply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnApply), NULL, this);
m_ckboxFreeDV700txClip->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this);
}
//-------------------------------------------------------------------------
// ExchangeData()
//-------------------------------------------------------------------------
void OptionsDlg::ExchangeData(int inout, bool storePersistent)
{
wxConfigBase *pConfig = wxConfigBase::Get();
if(inout == EXCHANGE_DATA_IN)
{
m_txtCtrlCallSign->SetValue(wxGetApp().m_callSign);
m_ckboxTestFrame->SetValue(wxGetApp().m_testFrames);
m_ckboxChannelNoise->SetValue(wxGetApp().m_channel_noise);
m_ckbox_events->SetValue(wxGetApp().m_events);
m_txt_spam_timer->SetValue(wxString::Format(wxT("%i"),wxGetApp().m_events_spam_timer));
m_txt_events_regexp_match->SetValue(wxGetApp().m_events_regexp_match);
m_txt_events_regexp_replace->SetValue(wxGetApp().m_events_regexp_replace);
m_ckbox_udp_enable->SetValue(wxGetApp().m_udp_enable);
m_txt_udp_port->SetValue(wxString::Format(wxT("%i"),wxGetApp().m_udp_port));
#ifdef SHORT_VARICODE
if (wxGetApp().m_textEncoding == 1)
m_rb_textEncoding1->SetValue(true);
if (wxGetApp().m_textEncoding == 2)
m_rb_textEncoding2->SetValue(true);
#endif
m_ckboxEnableChecksum->SetValue(wxGetApp().m_enable_checksum);
m_ckboxFreeDV700txClip->SetValue(wxGetApp().m_FreeDV700txClip);
}
if(inout == EXCHANGE_DATA_OUT)
{
wxGetApp().m_callSign = m_txtCtrlCallSign->GetValue();
wxGetApp().m_testFrames = m_ckboxTestFrame->GetValue();
wxGetApp().m_channel_noise = m_ckboxChannelNoise->GetValue();
wxGetApp().m_events = m_ckbox_events->GetValue();
long spam_timer;
m_txt_spam_timer->GetValue().ToLong(&spam_timer);
wxGetApp().m_events_spam_timer = (int)spam_timer;
// make sure regexp lists are terminated by a \n
if (m_txt_events_regexp_match->GetValue().Last() != '\n') {
m_txt_events_regexp_match->SetValue(m_txt_events_regexp_match->GetValue()+'\n');
}
if (m_txt_events_regexp_replace->GetValue().Last() != '\n') {
m_txt_events_regexp_replace->SetValue(m_txt_events_regexp_replace->GetValue()+'\n');
}
wxGetApp().m_events_regexp_match = m_txt_events_regexp_match->GetValue();
wxGetApp().m_events_regexp_replace = m_txt_events_regexp_replace->GetValue();
wxGetApp().m_udp_enable = m_ckbox_udp_enable->GetValue();
long port;
m_txt_udp_port->GetValue().ToLong(&port);
wxGetApp().m_udp_port = (int)port;
#ifdef SHORT_VARICODE
if (m_rb_textEncoding1->GetValue())
wxGetApp().m_textEncoding = 1;
if (m_rb_textEncoding2->GetValue())
wxGetApp().m_textEncoding = 2;
#endif
wxGetApp().m_enable_checksum = m_ckboxEnableChecksum->GetValue();
wxGetApp().m_FreeDV700txClip = m_ckboxFreeDV700txClip->GetValue();
if (storePersistent) {
pConfig->Write(wxT("/Data/CallSign"), wxGetApp().m_callSign);
#ifdef SHORT_VARICODE
pConfig->Write(wxT("/Data/TextEncoding"), wxGetApp().m_textEncoding);
#endif
pConfig->Write(wxT("/Data/EnableChecksumOnMsgRx"), wxGetApp().m_enable_checksum);
pConfig->Write(wxT("/Events/enable"), wxGetApp().m_events);
pConfig->Write(wxT("/Events/spam_timer"), wxGetApp().m_events_spam_timer);
pConfig->Write(wxT("/Events/regexp_match"), wxGetApp().m_events_regexp_match);
pConfig->Write(wxT("/Events/regexp_replace"), wxGetApp().m_events_regexp_replace);
pConfig->Write(wxT("/UDP/enable"), wxGetApp().m_udp_enable);
pConfig->Write(wxT("/UDP/port"), wxGetApp().m_udp_port);
pConfig->Write(wxT("/FreeDV700/txClip"), wxGetApp().m_FreeDV700txClip);
pConfig->Flush();
}
}
delete wxConfigBase::Set((wxConfigBase *) NULL);
}
//-------------------------------------------------------------------------
// OnOK()
//-------------------------------------------------------------------------
void OptionsDlg::OnOK(wxCommandEvent& event)
{
ExchangeData(EXCHANGE_DATA_OUT, true);
//this->EndModal(wxID_OK);
g_modal = false;
this->Show(false);
}
//-------------------------------------------------------------------------
// OnCancel()
//-------------------------------------------------------------------------
void OptionsDlg::OnCancel(wxCommandEvent& event)
{
//this->EndModal(wxID_CANCEL);
g_modal = false;
this->Show(false);
}
//-------------------------------------------------------------------------
// OnApply()
//-------------------------------------------------------------------------
void OptionsDlg::OnApply(wxCommandEvent& event)
{
ExchangeData(EXCHANGE_DATA_OUT, true);
}
//-------------------------------------------------------------------------
// OnInitDialog()
//-------------------------------------------------------------------------
void OptionsDlg::OnInitDialog(wxInitDialogEvent& event)
{
ExchangeData(EXCHANGE_DATA_IN, false);
}
// immediately change flags rather using ExchangeData() so we can switch on and off at run time
void OptionsDlg::OnFreeDV700txClip(wxScrollEvent& event) {
wxGetApp().m_FreeDV700txClip = m_ckboxFreeDV700txClip->GetValue();
}
void OptionsDlg::updateEventLog(wxString event_in, wxString event_out) {
wxString event_in_with_serial, event_out_with_serial;
event_in_with_serial.Printf(_T("[%d] %s"), event_in_serial++, event_in);
event_out_with_serial.Printf(_T("[%d] %s"), event_out_serial++, event_out);
m_txt_events_in->AppendText(event_in_with_serial+"\n");
m_txt_events_out->AppendText(event_out_with_serial+"\n");
}

99
src/dlg_options.h 100644
View File

@ -0,0 +1,99 @@
//==========================================================================
// Name: dlg_options.h
// Purpose: Dialog for controlling misc FreeDV options
// Created: Nov 25 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __OPTIONS_DIALOG__
#define __OPTIONS_DIALOG__
#include "fdmdv2_main.h"
#include "fdmdv2_defines.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class OptionsDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class OptionsDlg : public wxDialog
{
public:
OptionsDlg( wxWindow* parent,
wxWindowID id = wxID_ANY, const wxString& title = _("Options"),
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(600,630),
long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~OptionsDlg();
void ExchangeData(int inout, bool storePersistent);
void updateEventLog(wxString event_in, wxString event_out);
bool enableEventsChecked() {return m_ckbox_events->GetValue();}
void SetSpamTimerLight(bool state) {
// Colours don't work on Windows
if (state) {
m_rb_spam_timer->SetForegroundColour( wxColour( 255,0 , 0 ) ); // red
m_rb_spam_timer->SetValue(true);
}
else {
m_rb_spam_timer->SetForegroundColour( wxColour( 0, 255, 0 ) ); // green
m_rb_spam_timer->SetValue(false);
}
}
protected:
// Handlers for events.
void OnOK(wxCommandEvent& event);
void OnCancel(wxCommandEvent& event);
void OnApply(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
void OnInitDialog(wxInitDialogEvent& event);
void OnFreeDV700txClip(wxScrollEvent& event);
wxTextCtrl *m_txtCtrlCallSign; // TODO: this should be renamed to tx_txtmsg, and rename all related incl persis strge
wxCheckBox *m_ckboxTestFrame;
wxCheckBox *m_ckboxChannelNoise;
wxCheckBox *m_ckboxFreeDV700txClip;
wxRadioButton *m_rb_textEncoding1;
wxRadioButton *m_rb_textEncoding2;
wxCheckBox *m_ckboxEnableChecksum;
wxCheckBox *m_ckbox_events;
wxTextCtrl *m_txt_events_regexp_match;
wxTextCtrl *m_txt_events_regexp_replace;
wxTextCtrl *m_txt_events_in;
wxTextCtrl *m_txt_events_out;
wxTextCtrl *m_txt_spam_timer;
wxRadioButton *m_rb_spam_timer;
wxCheckBox *m_ckbox_udp_enable;
wxTextCtrl *m_txt_udp_port;
wxButton* m_sdbSizer5OK;
wxButton* m_sdbSizer5Cancel;
wxButton* m_sdbSizer5Apply;
unsigned int event_in_serial, event_out_serial;
private:
};
#endif // __OPTIONS_DIALOG__

416
src/dlg_ptt.cpp 100644
View File

@ -0,0 +1,416 @@
//==========================================================================
// Name: dlg_ptt.cpp
// Purpose: Subclasses dialog GUI for PTT Config. Creates simple
// wxWidgets dialog GUI to select real/virtual Comm ports.
// Date: May 11 2012
// Authors: David Rowe, David Witten, Joel Stanley
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include "dlg_ptt.h"
#include "fdmdv2_main.h"
#ifdef __WIN32__
#include <wx/msw/registry.h>
#endif
#ifdef __FreeBSD__
#include <glob.h>
#include <string.h>
#endif
#include <sstream>
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class ComPortsDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
ComPortsDlg::ComPortsDlg(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
this->SetSizer(mainSizer);
//----------------------------------------------------------------------
// Half Duplex Flag for VOX PTT
//----------------------------------------------------------------------
// DR: should this be on options dialog?
wxStaticBoxSizer* staticBoxSizer28 = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("VOX PTT Settings")), wxHORIZONTAL);
m_ckHalfDuplex = new wxCheckBox(this, wxID_ANY, _("Half Duplex"), wxDefaultPosition, wxSize(-1,-1), 0);
staticBoxSizer28->Add(m_ckHalfDuplex, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
m_ckLeftChannelVoxTone = new wxCheckBox(this, wxID_ANY, _("Left Channel Vox Tone"), wxDefaultPosition, wxSize(-1,-1), 0);
staticBoxSizer28->Add(m_ckLeftChannelVoxTone, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
mainSizer->Add(staticBoxSizer28, 0, wxEXPAND, 5);
//----------------------------------------------------------------------
// Hamlib for CAT PTT
//----------------------------------------------------------------------
wxStaticBoxSizer* staticBoxSizer18 = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("Hamlib Settings")), wxVERTICAL);
wxBoxSizer* gridSizer100 = new wxBoxSizer(wxHORIZONTAL);
/* Use Hamlib for PTT checkbox. */
m_ckUseHamlibPTT = new wxCheckBox(this, wxID_ANY, _("Use Hamlib PTT"), wxDefaultPosition, wxSize(-1, -1), 0);
m_ckUseHamlibPTT->SetValue(false);
gridSizer100->Add(m_ckUseHamlibPTT, 0, wxALIGN_CENTER_VERTICAL, 0);
/* Hamlib Rig Type combobox. */
gridSizer100->Add(new wxStaticText(this, wxID_ANY, _("Rig Model:"), wxDefaultPosition, wxDefaultSize, 0),
0, wxALIGN_CENTER_VERTICAL | wxLEFT, 20);
m_cbRigName = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, -1), 0, NULL, wxCB_DROPDOWN);
/* TODO(Joel): this is a hack. At the least, need to gurantee that m_hamLib
* exists. */
wxGetApp().m_hamlib->populateComboBox(m_cbRigName);
m_cbRigName->SetSelection(wxGetApp().m_intHamlibRig);
gridSizer100->Add(m_cbRigName, 0, wxALIGN_CENTER_VERTICAL, 0);
/* Hamlib Serial Port combobox. */
gridSizer100->Add(new wxStaticText(this, wxID_ANY, _("Serial Device:"), wxDefaultPosition, wxDefaultSize, 0),
0, wxALIGN_CENTER_VERTICAL | wxLEFT, 20);
m_cbSerialPort = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140, -1), 0, NULL, wxCB_DROPDOWN);
gridSizer100->Add(m_cbSerialPort, 0, wxALIGN_CENTER_VERTICAL, 0);
staticBoxSizer18->Add(gridSizer100, 1);
mainSizer->Add(staticBoxSizer18, 1);
//----------------------------------------------------------------------
// Serial port PTT
//----------------------------------------------------------------------
wxStaticBoxSizer* staticBoxSizer17 = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("Serial Port Settings")), wxVERTICAL);
mainSizer->Add(staticBoxSizer17, 1, wxEXPAND, 5);
wxStaticBoxSizer* staticBoxSizer31 = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("PTT Port")), wxVERTICAL);
staticBoxSizer17->Add(staticBoxSizer31, 1, wxEXPAND, 5);
#ifdef __WXMSW__
m_ckUseSerialPTT = new wxCheckBox(this, wxID_ANY, _("Use Serial Port PTT"), wxDefaultPosition, wxSize(-1,-1), 0);
m_ckUseSerialPTT->SetValue(false);
staticBoxSizer31->Add(m_ckUseSerialPTT, 0, wxALIGN_LEFT, 20);
wxArrayString m_listCtrlPortsArr;
m_listCtrlPorts = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1,45), m_listCtrlPortsArr, wxLB_SINGLE | wxLB_SORT);
staticBoxSizer31->Add(m_listCtrlPorts, 1, wxALIGN_CENTER, 0);
#endif
#ifdef __WXGTK__
wxBoxSizer* bSizer83;
bSizer83 = new wxBoxSizer(wxHORIZONTAL);
wxGridSizer* gridSizer200 = new wxGridSizer(1, 3, 0, 0);
m_ckUseSerialPTT = new wxCheckBox(this, wxID_ANY, _("Use Serial Port PTT"), wxDefaultPosition, wxSize(-1,-1), 0);
m_ckUseSerialPTT->SetValue(false);
gridSizer200->Add(m_ckUseSerialPTT, 1, wxALIGN_CENTER|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 2);
m_staticText12 = new wxStaticText(this, wxID_ANY, _("Serial Device: "), wxDefaultPosition, wxDefaultSize, 0);
m_staticText12->Wrap(-1);
gridSizer200->Add(m_staticText12, 1,wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 2);
m_cbCtlDevicePath = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140, -1), 0, NULL, wxCB_DROPDOWN);
gridSizer200->Add(m_cbCtlDevicePath, 1, wxEXPAND|wxALIGN_CENTER|wxALIGN_RIGHT, 2);
bSizer83->Add(gridSizer200, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
staticBoxSizer31->Add(bSizer83, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);
#endif
wxBoxSizer* boxSizer19 = new wxBoxSizer(wxVERTICAL);
staticBoxSizer17->Add(boxSizer19, 1, wxEXPAND, 5);
wxStaticBoxSizer* staticBoxSizer16 = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("Signal polarity")), wxHORIZONTAL);
boxSizer19->Add(staticBoxSizer16, 1, wxEXPAND|wxALIGN_CENTER|wxALIGN_RIGHT, 5);
wxGridSizer* gridSizer17 = new wxGridSizer(2, 2, 0, 0);
staticBoxSizer16->Add(gridSizer17, 1, wxEXPAND|wxALIGN_RIGHT, 5);
m_rbUseDTR = new wxRadioButton(this, wxID_ANY, _("Use DTR"), wxDefaultPosition, wxSize(-1,-1), 0);
m_rbUseDTR->SetToolTip(_("Toggle DTR line for PTT"));
m_rbUseDTR->SetValue(1);
gridSizer17->Add(m_rbUseDTR, 0, wxALIGN_CENTER|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5);
m_ckDTRPos = new wxCheckBox(this, wxID_ANY, _("DTR = +V"), wxDefaultPosition, wxSize(-1,-1), 0);
m_ckDTRPos->SetToolTip(_("Set Polarity of the DTR line"));
m_ckDTRPos->SetValue(false);
gridSizer17->Add(m_ckDTRPos, 0, wxALIGN_CENTER|wxALIGN_RIGHT, 5);
m_rbUseRTS = new wxRadioButton(this, wxID_ANY, _("Use RTS"), wxDefaultPosition, wxSize(-1,-1), 0);
m_rbUseRTS->SetToolTip(_("Toggle the RTS pin for PTT"));
m_rbUseRTS->SetValue(1);
gridSizer17->Add(m_rbUseRTS, 0, wxALIGN_CENTER|wxALIGN_RIGHT, 5);
m_ckRTSPos = new wxCheckBox(this, wxID_ANY, _("RTS = +V"), wxDefaultPosition, wxSize(-1,-1), 0);
m_ckRTSPos->SetValue(false);
m_ckRTSPos->SetToolTip(_("Set Polarity of the RTS line"));
gridSizer17->Add(m_ckRTSPos, 0, wxALIGN_CENTER|wxALIGN_RIGHT, 5);
//----------------------------------------------------------------------
// OK - Cancel - Apply
//----------------------------------------------------------------------
wxBoxSizer* boxSizer12 = new wxBoxSizer(wxHORIZONTAL);
m_buttonOK = new wxButton(this, wxID_OK, _("OK"), wxDefaultPosition, wxSize(-1,-1), 0);
m_buttonOK->SetDefault();
boxSizer12->Add(m_buttonOK, 0, wxLEFT|wxRIGHT|wxTOP|wxBOTTOM, 5);
m_buttonCancel = new wxButton(this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize(-1,-1), 0);
boxSizer12->Add(m_buttonCancel, 0, wxLEFT|wxRIGHT|wxTOP|wxBOTTOM, 5);
m_buttonApply = new wxButton(this, wxID_APPLY, _("Apply"), wxDefaultPosition, wxSize(-1,-1), 0);
boxSizer12->Add(m_buttonApply, 0, wxLEFT|wxRIGHT|wxTOP|wxBOTTOM, 5);
mainSizer->Add(boxSizer12, 0, wxLEFT|wxRIGHT|wxTOP|wxBOTTOM|wxALIGN_CENTER_HORIZONTAL, 5);
if ( GetSizer() )
{
GetSizer()->Fit(this);
}
Centre(wxBOTH);
// Connect events
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(ComPortsDlg::OnInitDialog), NULL, this);
m_ckUseHamlibPTT->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHamLibClicked), NULL, this);
m_ckUseSerialPTT->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseSerialClicked), NULL, this);
m_buttonOK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnOK), NULL, this);
m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnCancel), NULL, this);
m_buttonApply->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnApply), NULL, this);
}
//-------------------------------------------------------------------------
// ~ComPortsDlg()
//-------------------------------------------------------------------------
ComPortsDlg::~ComPortsDlg()
{
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(ComPortsDlg::OnInitDialog), NULL, this);
m_ckUseHamlibPTT->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHamLibClicked), NULL, this);
m_ckUseSerialPTT->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseSerialClicked), NULL, this);
m_buttonOK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnOK), NULL, this);
m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnCancel), NULL, this);
m_buttonApply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnApply), NULL, this);
}
//-------------------------------------------------------------------------
// OnInitDialog()
//-------------------------------------------------------------------------
void ComPortsDlg::OnInitDialog(wxInitDialogEvent& event)
{
populatePortList();
ExchangeData(EXCHANGE_DATA_IN);
}
//-------------------------------------------------------------------------
// populatePortList()
//-------------------------------------------------------------------------
void ComPortsDlg::populatePortList()
{
#ifdef __WXMSW__
m_listCtrlPorts->Clear();
m_cbSerialPort->Clear();
wxArrayString aStr;
wxRegKey key(wxRegKey::HKLM, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"));
if(!key.Exists())
{
return;
}
else
{
// Get the number of subkeys and enumerate them.
if(!key.Open(wxRegKey::Read))
{
return;
}
size_t subkeys;
size_t values;
if(!key.GetKeyInfo(&subkeys, NULL, &values, NULL))
{
return;
}
if(!key.HasValues())
{
return;
}
wxString key_name;
long el = 1;
key.GetFirstValue(key_name, el);
wxString valType;
wxString key_data;
for(unsigned int i = 0; i < values; i++)
{
key.QueryValue(key_name, key_data);
//wxPrintf("Value: %s Data: %s\n", key_name, key_data);
aStr.Add(key_data, 1);
key.GetNextValue(key_name, el);
}
}
m_listCtrlPorts->Append(aStr);
m_cbSerialPort->Append(aStr);
#endif
#ifdef __WXGTK__
m_cbSerialPort->Clear();
m_cbCtlDevicePath->Clear();
#ifdef __FreeBSD__
glob_t gl;
if(glob("/dev/tty*", GLOB_MARK, NULL, &gl)==0) {
for(unsigned int i=0; i<gl.gl_pathc; i++) {
if(gl.gl_pathv[i][strlen(gl.gl_pathv[i])-1]=='/')
continue;
/* Exclude pseudo TTYs */
if(gl.gl_pathv[i][8] >= 'l' && gl.gl_pathv[i][8] <= 's')
continue;
if(gl.gl_pathv[i][8] >= 'L' && gl.gl_pathv[i][8] <= 'S')
continue;
/* Exclude virtual TTYs */
if(gl.gl_pathv[i][8] == 'v')
continue;
/* Exclude initial-state and lock-state devices */
if(strchr(gl.gl_pathv[i], '.') != NULL)
continue;
m_cbSerialPort->Append(gl.gl_pathv[i]);
m_cbCtlDevicePath->Append(gl.gl_pathv[i]);
}
globfree(&gl);
}
#else
/* TODO(Joel): http://stackoverflow.com/questions/2530096/how-to-find-all-serial-devices-ttys-ttyusb-on-linux-without-opening-them */
m_cbSerialPort->Append("/dev/ttyUSB0");
m_cbSerialPort->Append("/dev/ttyUSB1");
m_cbSerialPort->Append("/dev/ttyS0");
m_cbSerialPort->Append("/dev/ttyS1");
m_cbCtlDevicePath->Clear();
m_cbCtlDevicePath->Append("/dev/ttyUSB0");
m_cbCtlDevicePath->Append("/dev/ttyUSB1");
m_cbCtlDevicePath->Append("/dev/ttyS0");
m_cbCtlDevicePath->Append("/dev/ttyS1");
#endif
#endif
}
//-------------------------------------------------------------------------
// ExchangeData()
//-------------------------------------------------------------------------
void ComPortsDlg::ExchangeData(int inout)
{
wxConfigBase *pConfig = wxConfigBase::Get();
wxString str;
if(inout == EXCHANGE_DATA_IN)
{
m_ckHalfDuplex->SetValue(wxGetApp().m_boolHalfDuplex);
m_ckLeftChannelVoxTone->SetValue(wxGetApp().m_leftChannelVoxTone);
m_ckUseHamlibPTT->SetValue(wxGetApp().m_boolHamlibUseForPTT);
m_cbRigName->SetSelection(wxGetApp().m_intHamlibRig);
m_cbSerialPort->SetValue(wxGetApp().m_strHamlibSerialPort);
m_ckUseSerialPTT->SetValue(wxGetApp().m_boolUseSerialPTT);
str = wxGetApp().m_strRigCtrlPort;
#ifdef __WXMSW__
m_listCtrlPorts->SetStringSelection(str);
#endif
#ifdef __WXGTK__
m_cbCtlDevicePath->SetValue(str);
#endif
m_rbUseRTS->SetValue(wxGetApp().m_boolUseRTS);
m_ckRTSPos->SetValue(wxGetApp().m_boolRTSPos);
m_rbUseDTR->SetValue(wxGetApp().m_boolUseDTR);
m_ckDTRPos->SetValue(wxGetApp().m_boolDTRPos);
}
if(inout == EXCHANGE_DATA_OUT)
{
wxGetApp().m_boolHalfDuplex = m_ckHalfDuplex->GetValue();
pConfig->Write(wxT("/Rig/HalfDuplex"), wxGetApp().m_boolHalfDuplex);
wxGetApp().m_leftChannelVoxTone = m_ckLeftChannelVoxTone->GetValue();
pConfig->Write(wxT("/Rig/leftChannelVoxTone"), wxGetApp().m_leftChannelVoxTone);
/* Hamlib settings. */
wxGetApp().m_boolHamlibUseForPTT = m_ckUseHamlibPTT->GetValue();
wxGetApp().m_intHamlibRig = m_cbRigName->GetSelection();
wxGetApp().m_strHamlibSerialPort = m_cbSerialPort->GetValue();
pConfig->Write(wxT("/Hamlib/UseForPTT"), wxGetApp().m_boolHamlibUseForPTT);
pConfig->Write(wxT("/Hamlib/RigName"), wxGetApp().m_intHamlibRig);
pConfig->Write(wxT("/Hamlib/SerialPort"), wxGetApp().m_strHamlibSerialPort);
/* Serial settings */
wxGetApp().m_boolUseSerialPTT = m_ckUseSerialPTT->IsChecked();
#ifdef __WXMSW__
wxGetApp().m_strRigCtrlPort = m_listCtrlPorts->GetStringSelection();
#endif
#ifdef __WXGTK__
wxGetApp().m_strRigCtrlPort = m_cbCtlDevicePath->GetValue();
#endif
wxGetApp().m_boolUseRTS = m_rbUseRTS->GetValue();
wxGetApp().m_boolRTSPos = m_ckRTSPos->IsChecked();
wxGetApp().m_boolUseDTR = m_rbUseDTR->GetValue();
wxGetApp().m_boolDTRPos = m_ckDTRPos->IsChecked();
pConfig->Write(wxT("/Rig/UseSerialPTT"), wxGetApp().m_boolUseSerialPTT);
pConfig->Write(wxT("/Rig/Port"), wxGetApp().m_strRigCtrlPort);
pConfig->Write(wxT("/Rig/UseRTS"), wxGetApp().m_boolUseRTS);
pConfig->Write(wxT("/Rig/RTSPolarity"), wxGetApp().m_boolRTSPos);
pConfig->Write(wxT("/Rig/UseDTR"), wxGetApp().m_boolUseDTR);
pConfig->Write(wxT("/Rig/DTRPolarity"), wxGetApp().m_boolDTRPos);
pConfig->Flush();
}
delete wxConfigBase::Set((wxConfigBase *) NULL);
}
//-------------------------------------------------------------------------
// PTTUseHamLibClicked()
//-------------------------------------------------------------------------
void ComPortsDlg::PTTUseHamLibClicked(wxCommandEvent& event)
{
m_ckUseSerialPTT->SetValue(false);
}
//-------------------------------------------------------------------------
// PTTUseSerialClicked()
//-------------------------------------------------------------------------
void ComPortsDlg::PTTUseSerialClicked(wxCommandEvent& event)
{
m_ckUseHamlibPTT->SetValue(false);
}
//-------------------------------------------------------------------------
// OnApply()
//-------------------------------------------------------------------------
void ComPortsDlg::OnApply(wxCommandEvent& event)
{
ExchangeData(EXCHANGE_DATA_OUT);
}
//-------------------------------------------------------------------------
// OnCancel()
//-------------------------------------------------------------------------
void ComPortsDlg::OnCancel(wxCommandEvent& event)
{
this->EndModal(wxID_CANCEL);
}
//-------------------------------------------------------------------------
// OnClose()
//-------------------------------------------------------------------------
void ComPortsDlg::OnOK(wxCommandEvent& event)
{
ExchangeData(EXCHANGE_DATA_OUT);
this->EndModal(wxID_OK);
}

91
src/dlg_ptt.h 100644
View File

@ -0,0 +1,91 @@
//==========================================================================
// Name: dlg_ptt.h
// Purpose: Subclasses dialog GUI for PTT Config.
//
// Created: May. 11, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __COMPORTS_DIALOG__
#define __COMPORTS_DIALOG__
#include "fdmdv2_main.h"
#include "hamlib.h"
#include <wx/settings.h>
#include <wx/xrc/xmlres.h>
#include <wx/xrc/xh_bmp.h>
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/checkbox.h>
#include <wx/listbox.h>
#include <wx/radiobut.h>
#include <wx/button.h>
#include <wx/spinctrl.h>
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class ComPortsDlg
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class ComPortsDlg : public wxDialog
{
public:
ComPortsDlg(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("PTT Config"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(450,300), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
virtual ~ComPortsDlg();
void ExchangeData(int inout);
protected:
wxCheckBox* m_ckHalfDuplex;
wxCheckBox* m_ckLeftChannelVoxTone;
/* Hamlib settings.*/
wxCheckBox *m_ckUseHamlibPTT;
wxComboBox *m_cbRigName;
wxComboBox *m_cbSerialPort;
Hamlib *m_hamlib;
/* Serial Settings */
wxListBox *m_listCtrlPorts;
wxCheckBox *m_ckUseSerialPTT;
wxStaticText *m_staticText12;
wxComboBox *m_cbCtlDevicePath;
wxRadioButton *m_rbUseDTR;
wxCheckBox *m_ckRTSPos;
wxRadioButton *m_rbUseRTS;
wxCheckBox *m_ckDTRPos;
/* Ok - Cancel - Apply */
wxButton* m_buttonOK;
wxButton* m_buttonCancel;
wxButton* m_buttonApply;
protected:
void populatePortList();
void PTTUseHamLibClicked(wxCommandEvent& event);
void PTTUseSerialClicked(wxCommandEvent& event);
void OnOK(wxCommandEvent& event);
void OnCancel(wxCommandEvent& event);
void OnApply(wxCommandEvent& event);
virtual void OnInitDialog(wxInitDialogEvent& event);
};
#endif // __COMPORTS_DIALOG__

View File

@ -0,0 +1,102 @@
//==========================================================================
// Name: fdmdv2_defines.h
// Purpose: Definitions used by plots derived from fdmdv2_plot class.
// Created: August 27, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_DEFINES__
#define __FDMDV2_DEFINES__
#include "wx/wx.h"
#include "freedv_api.h"
#include "freedv_api_internal.h"
// Spectrogram and Waterfall
#define MIN_MAG_DB -40.0 // min of spectrogram/waterfall magnitude axis
#define MAX_MAG_DB 0.0 // max of spectrogram/waterfall magnitude axis
#define STEP_MAG_DB 5.0 // magnitude axis step
#define BETA 0.95 // constant for time averaging spectrum data
#define MIN_F_HZ 0 // min freq on Waterfall and Spectrum
#define MAX_F_HZ 3000 // max freq on Waterfall and Spectrum
#define STEP_F_HZ 500 // major (e.g. text legend) freq step on Waterfall and Spectrum graticule
#define STEP_MINOR_F_HZ 100 // minor (ticks) freq step on Waterfall and Spectrum graticule
#define WATERFALL_SECS_Y 30 // number of seconds respresented by y axis of waterfall
#define WATERFALL_SECS_STEP 5 // graticule y axis steps of waterfall
#define DT 0.1 // time between real time graphing updates
#define FS 8000 // FDMDV modem sample rate
// Scatter diagram
#define SCATTER_MEM_SECS 10
// (symbols/frame)/(graphics update period) = symbols/s sent to scatter memory
// memory (symbols) = secs of memory * symbols/sec
#define SCATTER_MEM_SYMS_MAX ((int)(SCATTER_MEM_SECS*((FDMDV_NC_MAX+1)/DT)))
// Waveform plotting constants
#define WAVEFORM_PLOT_FS 400 // sample rate (points/s) of waveform plotted to screen
#define WAVEFORM_PLOT_TIME 5 // length or entire waveform on screen
#define WAVEFORM_PLOT_BUF ((int)(DT*WAVEFORM_PLOT_FS)) // number of new samples we plot per DT
// sample rate I/O & conversion constants
#define MAX_FPB 8096 // maximum value of portAudio framesPerBuffer
#define PA_FPB 1024 // nominal value of portAudio framesPerBuffer
#define SAMPLE_RATE 48000 // 48 kHz sampling rate rec. as we can trust accuracy of sound card
#define N8 160 // processing buffer size at 8 kHz
#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
#define N48 (N8*SAMPLE_RATE/FS) // processing buffer size at 48 kHz
#define NUM_CHANNELS 2 // I think most sound cards prefer stereo we will convert to mono
#define VOX_TONE_FREQ 1000.0 // optional left channel vox tone freq
#define VOX_TONE_AMP 30000 // optional left channel vox tone amp
#define MAX_BITS_PER_CODEC_FRAME 64 // 1600 bit/s mode
#define MAX_BYTES_PER_CODEC_FRAME (MAX_BITS_PER_CODEC_FRAME/8)
#define MAX_BITS_PER_FDMDV_FRAME 40 // 2000 bit/s mode
// Squelch
#define SQ_DEFAULT_SNR 2.0
// Level Gauge
#define FROM_RADIO_MAX 0.8
#define FROM_MIC_MAX 0.8
#define LEVEL_BETA 0.99
// SNR
#define SNRSLOW_BETA 0.5 // time constant for slow SNR for display
// Text messaging Data
#define MAX_CALLSIGN 80
#define MAX_EVENT_LOG 10
#define MAX_EVENT_RULES 100
enum
{
ID_ROTATE_LEFT = wxID_HIGHEST + 1,
ID_ROTATE_RIGHT,
ID_RESIZE,
ID_PAINT_BG
};
// Codec 2 LPC Post Filter defaults, from codec-dev/src/quantise.c
#define CODEC2_LPC_PF_GAMMA 0.5
#define CODEC2_LPC_PF_BETA 0.2
#endif //__FDMDV2_DEFINES__

3697
src/fdmdv2_main.cpp 100644

File diff suppressed because it is too large Load Diff

614
src/fdmdv2_main.h 100644
View File

@ -0,0 +1,614 @@
//==========================================================================
// Name: fdmdv2_main.h
//
// Purpose: Declares simple wxWidgets application with GUI.
// Created: Apr. 9, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General License version 2.1,
// as published by the Free Software Foundation. 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 License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_MAIN__
#define __FDMDV2_MAIN__
#include "version.h"
#ifndef _NO_AUTOTOOLS_
#include "../config.h"
#endif
#include <wx/wx.h>
#include <wx/tglbtn.h>
#include <wx/app.h>
//#include <wx/aboutdlg.h>
#include "wx/rawbmp.h"
#include "wx/file.h"
#include "wx/filename.h"
#include "wx/config.h"
#include <wx/fileconf.h>
#include "wx/graphics.h"
#include "wx/mstream.h"
#include "wx/wfstream.h"
#include "wx/quantize.h"
#include "wx/scopedptr.h"
#include "wx/stopwatch.h"
#include "wx/versioninfo.h"
#include <wx/sound.h>
#include <wx/url.h>
#include <wx/sstream.h>
#include <wx/listbox.h>
#include <wx/textdlg.h>
#include <wx/regex.h>
#include <wx/socket.h>
#include <samplerate.h>
#include <hamlib.h>
#include <stdint.h>
#include <speex/speex_preprocess.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <termios.h>
#include <sys/ioctl.h>
#endif
#include "codec2.h"
#include "codec2_fdmdv.h"
#include "codec2_fifo.h"
#include "golay23.h"
#include "modem_stats.h"
#include "topFrame.h"
#include "dlg_ptt.h"
#include "dlg_options.h"
#include "fdmdv2_plot.h"
#include "fdmdv2_plot_scalar.h"
#include "fdmdv2_plot_scatter.h"
#include "fdmdv2_plot_waterfall.h"
#include "fdmdv2_plot_spectrum.h"
#include "fdmdv2_pa_wrapper.h"
#include "sndfile.h"
#include "portaudio.h"
#include "dlg_audiooptions.h"
#include "dlg_filter.h"
#include "dlg_options.h"
#include "varicode.h"
#include "sox_biquad.h"
#include "comp_prim.h"
#define _USE_TIMER 1
#define _USE_ONIDLE 1
#define _DUMMY_DATA 1
//#define _AUDIO_PASSTHROUGH 1
#define _REFRESH_TIMER_PERIOD (DT*1000)
//#define _USE_ABOUT_DIALOG 1
enum {
ID_START = wxID_HIGHEST,
ID_TIMER_WATERFALL,
ID_TIMER_SPECTRUM,
ID_TIMER_SCATTER,
ID_TIMER_SCALAR
};
#define EXCHANGE_DATA_IN 0
#define EXCHANGE_DATA_OUT 1
#ifdef _WIN32
#define COM_HANDLE_INVALID INVALID_HANDLE_VALUE
typedef HANDLE com_handle_t;
#else
#define COM_HANDLE_INVALID -1
typedef int com_handle_t;
#endif
extern int g_nSoundCards;
extern int g_soundCard1InDeviceNum;
extern int g_soundCard1OutDeviceNum;
extern int g_soundCard1SampleRate;
extern int g_soundCard2InDeviceNum;
extern int g_soundCard2OutDeviceNum;
extern int g_soundCard2SampleRate;
class MainFrame;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class MainApp
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class MainApp : public wxApp
{
public:
virtual bool OnInit();
virtual int OnExit();
wxString m_strVendName;
wxString m_StrAppName;
wxString m_textNumChOut;
wxString m_textNumChIn;
wxString m_strRxInAudio;
wxString m_strRxOutAudio;
wxString m_textVoiceInput;
wxString m_textVoiceOutput;
wxString m_strSampleRate;
wxString m_strBitrate;
// PTT -----------------------------------
bool m_boolHalfDuplex;
bool m_boolHamlibUseForPTT;
unsigned int m_intHamlibRig;
wxString m_strHamlibSerialPort;
Hamlib *m_hamlib;
bool m_boolUseSerialPTT;
wxString m_strRigCtrlPort;
bool m_boolUseRTS;
bool m_boolRTSPos;
bool m_boolUseDTR;
bool m_boolDTRPos;
// Play/Rec files
wxString m_playFileToMicInPath;
wxString m_recFileFromRadioPath;
unsigned int m_recFileFromRadioSecs;
wxString m_playFileFromRadioPath;
// Options dialog
wxString m_callSign;
bool m_events;
int m_events_spam_timer;
unsigned int m_textEncoding;
bool m_enable_checksum;
wxString m_events_regexp_match;
wxString m_events_regexp_replace;
bool m_snrSlow;
// LPC Post Filter
bool m_codec2LPCPostFilterEnable;
bool m_codec2LPCPostFilterBassBoost;
float m_codec2LPCPostFilterGamma;
float m_codec2LPCPostFilterBeta;
// Speex Pre-Processor
bool m_speexpp_enable;
// Mic In Equaliser
float m_MicInBassFreqHz;
float m_MicInBassGaindB;
float m_MicInTrebleFreqHz;
float m_MicInTrebleGaindB;
float m_MicInMidFreqHz;
float m_MicInMidGaindB;
float m_MicInMidQ;
bool m_MicInEQEnable;
// Spk Out Equaliser
float m_SpkOutBassFreqHz;
float m_SpkOutBassGaindB;
float m_SpkOutTrebleFreqHz;
float m_SpkOutTrebleGaindB;
float m_SpkOutMidFreqHz;
float m_SpkOutMidGaindB;
float m_SpkOutMidQ;
bool m_SpkOutEQEnable;
// Flags for displaying windows
int m_show_wf;
int m_show_spect;
int m_show_scatter;
int m_show_timing;
int m_show_freq;
int m_show_speech_in;
int m_show_speech_out;
int m_show_demod_in;
int m_show_test_frame_errors;
int m_show_test_frame_errors_hist;
// optional vox trigger tone
bool m_leftChannelVoxTone;
// UDP control port
bool m_udp_enable;
int m_udp_port;
// notebook display after tx->rxtransition
int m_rxNbookCtrl;
wxRect m_rTopWindow;
int m_framesPerBuffer;
bool loadConfig();
bool saveConfig();
// misc
bool m_testFrames;
bool m_channel_noise;
float m_channel_snr_dB;
int FilterEvent(wxEvent& event);
MainFrame *frame;
bool m_FreeDV700txClip;
protected:
};
// declare global static function wxGetApp()
DECLARE_APP(MainApp)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// paCallBackData
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
typedef struct
{
// libresample states for 48 to 8 kHz conversions
SRC_STATE *insrc1;
SRC_STATE *outsrc1;
SRC_STATE *insrc2;
SRC_STATE *outsrc2;
SRC_STATE *insrcsf;
// FIFOs attached to first sound card
struct FIFO *infifo1;
struct FIFO *outfifo1;
// FIFOs attached to second sound card
struct FIFO *infifo2;
struct FIFO *outfifo2;
// FIFOs for rx process
struct FIFO *rxinfifo;
struct FIFO *rxoutfifo;
int inputChannels1, inputChannels2;
// EQ filter states
void *sbqMicInBass;
void *sbqMicInTreble;
void *sbqMicInMid;
void *sbqSpkOutBass;
void *sbqSpkOutTreble;
void *sbqSpkOutMid;
bool micInEQEnable;
bool spkOutEQEnable;
// optional loud tone on left channel to reliably trigger vox
bool leftChannelVoxTone;
float voxTonePhase;
} paCallBackData;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// panel with custom loop checkbox for play file dialog
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class MyExtraPlayFilePanel : public wxPanel
{
public:
MyExtraPlayFilePanel(wxWindow *parent);
void setLoopPlayFileToMicIn(bool checked) { m_cb->SetValue(checked); }
bool getLoopPlayFileToMicIn(void) { return m_cb->GetValue(); }
private:
wxCheckBox *m_cb;
};
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// panel with custom Seconds-to-record control for record file dialog
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class MyExtraRecFilePanel : public wxPanel
{
public:
MyExtraRecFilePanel(wxWindow *parent);
~MyExtraRecFilePanel()
{
wxLogDebug("Destructor\n");
}
void setSecondsToRecord(wxString value) { m_secondsToRecord->SetValue(value); }
wxString getSecondsToRecord(void)
{
wxLogDebug("getSecondsToRecord: %s\n",m_secondsToRecord->GetValue());
return m_secondsToRecord->GetValue();
}
private:
wxTextCtrl *m_secondsToRecord;
};
class txRxThread;
class UDPThread;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class MainFrame
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class MainFrame : public TopFrame
{
public:
MainFrame(wxWindow *parent);
virtual ~MainFrame();
PlotSpectrum* m_panelSpectrum;
PlotWaterfall* m_panelWaterfall;
PlotScatter* m_panelScatter;
PlotScalar* m_panelTimeOffset;
PlotScalar* m_panelFreqOffset;
PlotScalar* m_panelSpeechIn;
PlotScalar* m_panelSpeechOut;
PlotScalar* m_panelDemodIn;
PlotScalar* m_panelTestFrameErrors;
PlotScalar* m_panelTestFrameErrorsHist;
bool m_RxRunning;
PortAudioWrap *m_rxInPa;
PortAudioWrap *m_rxOutPa;
PortAudioWrap *m_txInPa;
PortAudioWrap *m_txOutPa;
PaError m_rxErr;
PaError m_txErr;
txRxThread* m_txRxThread;
bool OpenHamlibRig();
void SetupSerialPort(void);
void CloseSerialPort(void);
void SerialPTTRx(void);
bool m_modal;
#ifdef _USE_TIMER
wxTimer m_plotTimer;
#endif
void destroy_fifos(void);
void destroy_src(void);
void autoDetectSoundCards(PortAudioWrap *pa);
static int rxCallback(
const void *inBuffer,
void *outBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *outTime,
PaStreamCallbackFlags statusFlags,
void *userData
);
static int txCallback(
const void *inBuffer,
void *outBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *outTime,
PaStreamCallbackFlags statusFlags,
void *userData
);
void initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevice,
int soundCard, int sampleRate, int inputChannels);
void togglePTT(void);
wxIPV4address m_udp_addr;
wxDatagramSocket *m_udp_sock;
UDPThread *m_UDPThread;
void startUDPThread(void);
void stopUDPThread(void);
int PollUDP();
bool m_schedule_restore;
protected:
#ifdef _WIN32
#define COM_HANDLE_INVALID INVALID_HANDLE_VALUE
com_handle_t com_handle;
#else
#define COM_HANDLE_INVALID -1
com_handle_t com_handle;
#endif
void raiseDTR(void);
void lowerDTR(void);
void raiseRTS(void);
void lowerRTS(void);
bool openComPort(const char *port);
void closeComPort(void);
void setsnrBeta(bool snrSlow);
// protected event handlers
virtual void OnCloseFrame(wxCloseEvent& event);
void OnExitClick(wxCommandEvent& event);
void startTxStream();
void startRxStream();
void stopTxStream();
void stopRxStream();
void abortTxStream();
void abortRxStream();
void OnTop(wxCommandEvent& event);
void OnExit( wxCommandEvent& event );
void OnToolsAudio( wxCommandEvent& event );
void OnToolsAudioUI( wxUpdateUIEvent& event );
void OnToolsComCfg( wxCommandEvent& event );
void OnToolsComCfgUI( wxUpdateUIEvent& event );
void OnToolsFilter( wxCommandEvent& event );
void OnToolsOptions(wxCommandEvent& event);
void OnToolsOptionsUI(wxUpdateUIEvent& event);
void OnPlayFileToMicIn( wxCommandEvent& event );
void OnRecFileFromRadio( wxCommandEvent& event );
void OnPlayFileFromRadio( wxCommandEvent& event );
void OnHelpCheckUpdates( wxCommandEvent& event );
void OnHelpCheckUpdatesUI( wxUpdateUIEvent& event );
void OnHelpAbout( wxCommandEvent& event );
void OnCmdSliderScroll( wxScrollEvent& event );
// void OnSliderScrollBottom( wxScrollEvent& event );
// void OnCmdSliderScrollChanged( wxScrollEvent& event );
// void OnSliderScrollTop( wxScrollEvent& event );
void OnCheckSQClick( wxCommandEvent& event );
void OnCheckSNRClick( wxCommandEvent& event );
// Toggle Buttons
void OnTogBtnSplitClick(wxCommandEvent& event);
void OnTogBtnAnalogClick(wxCommandEvent& event);
void OnTogBtnRxID( wxCommandEvent& event );
void OnTogBtnTxID( wxCommandEvent& event );
void OnTogBtnPTT( wxCommandEvent& event );
void OnTogBtnOnOff( wxCommandEvent& event );
void OnCallSignReset( wxCommandEvent& event );
void OnBerReset( wxCommandEvent& event );
//System Events
void OnPaint(wxPaintEvent& event);
void OnSize( wxSizeEvent& event );
void OnUpdateUI( wxUpdateUIEvent& event );
void OnDeleteConfig(wxCommandEvent&);
#ifdef _USE_TIMER
void OnTimer(wxTimerEvent &evt);
#endif
#ifdef _USE_ONIDLE
void OnIdle(wxIdleEvent &evt);
#endif
private:
bool m_useMemory;
wxTextCtrl* m_tc;
int m_zoom;
float m_snrBeta;
// Callsign/text messaging
char m_callsign[MAX_CALLSIGN];
char *m_pcallsign;
unsigned int m_checksumGood;
unsigned int m_checksumBad;
// Events
void processTxtEvent(char event[]);
class OptionsDlg *optionsDlg;
wxTimer spamTimer[MAX_EVENT_RULES];
// level Gauge
float m_maxLevel;
// flags to indicate when new EQ filters need to be designed
bool m_newMicInFilter;
bool m_newSpkOutFilter;
void* designAnEQFilter(const char filterType[], float freqHz, float gaindB, float Q = 0.0);
void designEQFilters(paCallBackData *cb);
void deleteEQFilters(paCallBackData *cb);
};
void txRxProcessing();
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// class txRxThread - experimental tx/rx processing thread
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class txRxThread : public wxThread
{
public:
txRxThread(void) : wxThread(wxTHREAD_JOINABLE) { m_run = 1; }
// thread execution starts here
void *Entry()
{
while (m_run)
{
txRxProcessing();
wxThread::Sleep(20);
}
return NULL;
}
// called when the thread exits - whether it terminates normally or is
// stopped with Delete() (but not when it is Kill()ed!)
void OnExit() { }
public:
bool m_run;
};
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// class UDPThread - waits for UDP messages
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class UDPThread : public wxThread
{
public:
UDPThread(void) : wxThread(wxTHREAD_JOINABLE) { m_run = 1; }
// thread execution starts here
void *Entry();
// called when the thread exits - whether it terminates normally or is
// stopped with Delete() (but not when it is Kill()ed!)
void OnExit() { }
public:
MainFrame *mf;
bool m_run;
};
void resample_for_plot(struct FIFO *plotFifo, short buf[], int length, int fs);
int resample(SRC_STATE *src,
short output_short[],
short input_short[],
int output_sample_rate,
int input_sample_rate,
int length_output_short, // maximum output array length in samples
int length_input_short
);
void txRxProcessing();
void per_frame_rx_processing(
FIFO *output_fifo, // decoded speech samples
FIFO *input_fifo // modem samples input to demod
);
// FreeDv API calls this when there is a test frame that needs a-plottin'
void my_freedv_put_error_pattern(void *state, short error_pattern[], int sz_error_pattern);
// FreeDv API calls these puppies when it needs/receives a text char
char my_get_next_tx_char(void *callback_state);
void my_put_next_rx_char(void *callback_state, char c);
#endif //__FDMDV2_MAIN__

View File

@ -0,0 +1,324 @@
//==========================================================================
// Name: fdmdv2_pa_wrapper.cpp
// Purpose: Implements a wrapper class around the PortAudio library.
// Created: August 12, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include "fdmdv2_pa_wrapper.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// PortAudioWrap()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PortAudioWrap::PortAudioWrap()
{
m_pStream = NULL;
m_pUserData = NULL;
m_samplerate = 0;
m_framesPerBuffer = 0;
m_statusFlags = 0;
m_pStreamCallback = NULL;
m_pStreamFinishedCallback = NULL;
m_pTimeInfo = 0;
m_newdata = false;
// loadData();
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// ~PortAudioWrap()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PortAudioWrap::~PortAudioWrap()
{
}
//----------------------------------------------------------------
// streamOpen()
//----------------------------------------------------------------
PaError PortAudioWrap::streamOpen()
{
return Pa_OpenStream(
&m_pStream,
m_inputBuffer.device == paNoDevice ? NULL : &m_inputBuffer,
m_outputBuffer.device == paNoDevice ? NULL : &m_outputBuffer,
m_samplerate,
m_framesPerBuffer,
m_statusFlags,
*m_pStreamCallback,
m_pUserData
);
}
//----------------------------------------------------------------
// streamStart()
//----------------------------------------------------------------
PaError PortAudioWrap::streamStart()
{
return Pa_StartStream(m_pStream);
}
//----------------------------------------------------------------
// streamClose()
//----------------------------------------------------------------
PaError PortAudioWrap::streamClose()
{
if(isOpen())
{
PaError rv = Pa_CloseStream(m_pStream);
return rv;
}
else
{
return paNoError;
}
}
//----------------------------------------------------------------
// terminate()
//----------------------------------------------------------------
void PortAudioWrap::terminate()
{
if(Pa_IsStreamStopped(m_pStream) != paNoError)
{
Pa_StopStream(m_pStream);
}
Pa_Terminate();
}
//----------------------------------------------------------------
// stop()
//----------------------------------------------------------------
void PortAudioWrap::stop()
{
Pa_StopStream(m_pStream);
}
//----------------------------------------------------------------
// abort()
//----------------------------------------------------------------
void PortAudioWrap::abort()
{
Pa_AbortStream(m_pStream);
}
//----------------------------------------------------------------
// isStopped()
//----------------------------------------------------------------
bool PortAudioWrap::isStopped() const
{
PaError ret = Pa_IsStreamStopped(m_pStream);
return ret;
}
//----------------------------------------------------------------
// isActive()
//----------------------------------------------------------------
bool PortAudioWrap::isActive() const
{
PaError ret = Pa_IsStreamActive(m_pStream);
return ret;
}
//----------------------------------------------------------------
// isOpen()
//----------------------------------------------------------------
bool PortAudioWrap::isOpen() const
{
return (m_pStream != NULL);
}
//----------------------------------------------------------------
// getDefaultInputDevice()
//----------------------------------------------------------------
PaDeviceIndex PortAudioWrap::getDefaultInputDevice()
{
return Pa_GetDefaultInputDevice();
}
//----------------------------------------------------------------
// getDefaultOutputDevice()
//----------------------------------------------------------------
PaDeviceIndex PortAudioWrap::getDefaultOutputDevice()
{
return Pa_GetDefaultOutputDevice();
}
//----------------------------------------------------------------
// setInputChannelCount()
//----------------------------------------------------------------
PaError PortAudioWrap::setInputChannelCount(int count)
{
m_inputBuffer.channelCount = count;
return paNoError;
}
//----------------------------------------------------------------
// getInputChannelCount()
//----------------------------------------------------------------
PaError PortAudioWrap::getInputChannelCount()
{
return m_inputBuffer.channelCount;
}
//----------------------------------------------------------------
// setInputSampleFormat()
//----------------------------------------------------------------
PaError PortAudioWrap::setInputSampleFormat(PaSampleFormat format)
{
m_inputBuffer.sampleFormat = format;
return paNoError;
}
//----------------------------------------------------------------
// setInputLatency()
//----------------------------------------------------------------
PaError PortAudioWrap::setInputLatency(PaTime latency)
{
m_inputBuffer.suggestedLatency = latency;
return paNoError;
}
//----------------------------------------------------------------
// setInputHostApiStreamInfo()
//----------------------------------------------------------------
void PortAudioWrap::setInputHostApiStreamInfo(void *info)
{
m_inputBuffer.hostApiSpecificStreamInfo = info;
}
//----------------------------------------------------------------
// getInputDefaultLowLatency()
//----------------------------------------------------------------
PaTime PortAudioWrap::getInputDefaultLowLatency()
{
return Pa_GetDeviceInfo(m_inputBuffer.device)->defaultLowInputLatency;
}
//----------------------------------------------------------------
// setOutputChannelCount()
//----------------------------------------------------------------
PaError PortAudioWrap::setOutputChannelCount(int count)
{
m_outputBuffer.channelCount = count;
return paNoError;
}
//----------------------------------------------------------------
// getOutputChannelCount()
//----------------------------------------------------------------
const int PortAudioWrap::getOutputChannelCount()
{
return m_outputBuffer.channelCount;
}
//----------------------------------------------------------------
// getDeviceName()
//----------------------------------------------------------------
const char *PortAudioWrap::getDeviceName(PaDeviceIndex dev)
{
const PaDeviceInfo *info;
info = Pa_GetDeviceInfo(dev);
return info->name;
}
//----------------------------------------------------------------
// setOutputSampleFormat()
//----------------------------------------------------------------
PaError PortAudioWrap::setOutputSampleFormat(PaSampleFormat format)
{
m_outputBuffer.sampleFormat = format;
return paNoError;
}
//----------------------------------------------------------------
// setOutputLatency()
//----------------------------------------------------------------
PaError PortAudioWrap::setOutputLatency(PaTime latency)
{
m_outputBuffer.suggestedLatency = latency;
return paNoError;
}
//----------------------------------------------------------------
// setOutputHostApiStreamInfo()
//----------------------------------------------------------------
void PortAudioWrap::setOutputHostApiStreamInfo(void *info)
{
m_outputBuffer.hostApiSpecificStreamInfo = info;
}
//----------------------------------------------------------------
// getOutputDefaultLowLatency()
//----------------------------------------------------------------
PaTime PortAudioWrap::getOutputDefaultLowLatency()
{
return Pa_GetDeviceInfo(m_outputBuffer.device)->defaultLowOutputLatency;
}
//----------------------------------------------------------------
// setFramesPerBuffer()
//----------------------------------------------------------------
PaError PortAudioWrap::setFramesPerBuffer(unsigned long size)
{
m_framesPerBuffer = size;
return paNoError;
}
//----------------------------------------------------------------
// setSampleRate()
//----------------------------------------------------------------
PaError PortAudioWrap::setSampleRate(unsigned long rate)
{
m_samplerate = rate;
return paNoError;
}
//----------------------------------------------------------------
// setStreamFlags()
//----------------------------------------------------------------
PaError PortAudioWrap::setStreamFlags(PaStreamFlags flags)
{
m_statusFlags = flags;
return paNoError;
}
//----------------------------------------------------------------
// setInputDevice()
//----------------------------------------------------------------
PaError PortAudioWrap::setInputDevice(PaDeviceIndex index)
{
m_inputBuffer.device = index;
return paNoError;
}
//----------------------------------------------------------------
// setOutputDevice()
//----------------------------------------------------------------
PaError PortAudioWrap::setOutputDevice(PaDeviceIndex index)
{
m_outputBuffer.device = index;
return paNoError;
}
//----------------------------------------------------------------
// setCallback()
//----------------------------------------------------------------
PaError PortAudioWrap::setCallback(PaStreamCallback *callback)
{
m_pStreamCallback = callback;
return paNoError;
}

View File

@ -0,0 +1,115 @@
//==========================================================================
// Name: fdmdv2_pa_wrapper.h
// Purpose: Defines a wrapper class around PortAudio
// Created: August 12, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <stdio.h>
#include <math.h>
#include "fdmdv2_defines.h"
#include "codec2_fdmdv.h"
#include "codec2.h"
#include "portaudio.h"
#define PA_SAMPLE_TYPE paInt16 //paFloat32
#define FRAMES_PER_BUFFER (64)
typedef float SAMPLE;
class PortAudioWrap
{
public:
PortAudioWrap();
~PortAudioWrap();
// float m_av_mag[FDMDV_NSPEC];
private:
PaStream *m_pStream;
void *m_pUserData;
PaStreamCallback *m_pStreamCallback;
PaStreamFinishedCallback *m_pStreamFinishedCallback;
const PaStreamCallbackTimeInfo *m_pTimeInfo;
struct FDMDV *m_pFDMDV_state;
PaStreamParameters m_inputBuffer;
PaStreamParameters m_outputBuffer;
int m_samplerate;
unsigned long m_framesPerBuffer;
PaStreamCallbackFlags m_statusFlags;
bool m_newdata;
public:
void averageData(float mag_dB[]);
int getDeviceCount() { return Pa_GetDeviceCount(); }
PaDeviceIndex getDefaultInputDevice();
PaDeviceIndex getDefaultOutputDevice();
PaStreamParameters *getDeviceInfo(PaDeviceIndex idx);
PaError setFramesPerBuffer(unsigned long size);
PaError setSampleRate(unsigned long size);
PaError setStreamFlags(PaStreamFlags flags);
PaError setCallback(PaStreamCallback *m_pStreamCallback);
PaError setStreamCallback(PaStream *stream, PaStreamCallback* callback) { m_pStreamCallback = callback; return 0;}
PaError setStreamFinishedCallback(PaStream *stream, PaStreamFinishedCallback* m_pStreamFinishedCallback);
void setInputBuffer(const PaStreamParameters& inputBuffer) {this->m_inputBuffer = inputBuffer;}
PaError setInputDevice(PaDeviceIndex dev);
PaError setInputChannelCount(int count);
int getInputChannelCount();
PaError setInputSampleFormat(PaSampleFormat format);
PaError setInputSampleRate(PaSampleFormat format);
PaError setInputLatency(PaTime latency);
void setInputHostApiStreamInfo(void *info = NULL);
PaTime getInputDefaultLowLatency();
const char *getDeviceName(PaDeviceIndex dev);
PaError setOutputDevice(PaDeviceIndex dev);
PaError setOutputChannelCount(int count);
const int getOutputChannelCount();
PaError setOutputSampleFormat(PaSampleFormat format);
PaError setOutputLatency(PaTime latency);
void setOutputHostApiStreamInfo(void *info = NULL);
PaTime getOutputDefaultLowLatency();
void setFdmdvState(FDMDV* fdmdv_state) {this->m_pFDMDV_state = fdmdv_state;}
void setOutputBuffer(const PaStreamParameters& outputBuffer) {this->m_outputBuffer = outputBuffer;}
void setTimeInfo(PaStreamCallbackTimeInfo* timeInfo) {this->m_pTimeInfo = timeInfo;}
void setUserData(void* userData) {this->m_pUserData = userData;}
unsigned long getFramesPerBuffer() const {return m_framesPerBuffer;}
const PaStreamParameters& getInputBuffer() const {return m_inputBuffer;}
const PaStreamParameters& getOutputBuffer() const {return m_outputBuffer;}
const PaStreamCallbackFlags& getStatusFlags() const {return m_statusFlags;}
FDMDV* getFdmdvState() {return m_pFDMDV_state;}
int getSamplerate() const {return m_samplerate;}
PaStream* getStream() {return m_pStream;}
void *getUserData() {return m_pUserData;}
bool getDataAvail() {return m_newdata;}
PaError streamStart();
PaError streamClose();
PaError streamOpen();
void terminate();
void stop();
void abort();
bool isOpen() const;
bool isStopped() const;
bool isActive() const;
// void loadData();
};

283
src/fdmdv2_plot.cpp 100644
View File

@ -0,0 +1,283 @@
//==========================================================================
// Name: fdmdv2_plot.cpp
// Purpose: Implements simple wxWidgets application with GUI.
// Created: Apr. 9, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <string.h>
#include "fdmdv2_plot.h"
BEGIN_EVENT_TABLE(PlotPanel, wxPanel)
EVT_PAINT (PlotPanel::OnPaint)
EVT_MOTION (PlotPanel::OnMouseMove)
EVT_LEFT_DOWN (PlotPanel::OnMouseLeftDown)
EVT_LEFT_UP (PlotPanel::OnMouseLeftUp)
EVT_RIGHT_DOWN (PlotPanel::OnMouseRightDown)
EVT_MOUSEWHEEL (PlotPanel::OnMouseWheelMoved)
EVT_SIZE (PlotPanel::OnSize)
EVT_SHOW (PlotPanel::OnShow)
END_EVENT_TABLE()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotPanel(wxFrame* parent) : wxPanel(parent)
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PlotPanel::PlotPanel(wxFrame* parent) : wxPanel(parent)
{
m_pNoteBook = (wxAuiNotebook *) parent;
m_pTopFrame = (MainFrame *)m_pNoteBook->GetParent();
m_zoomFactor = 1.0;
m_pBmp = NULL;
m_pPix = NULL;
m_firstPass = true;
m_line_color = 0;
m_newdata = false;
m_clip = false;
m_use_bitmap = true;
m_rubberBand = false;
m_mouseDown = false;
m_penShortDash = wxPen(wxColor(0xA0, 0xA0, 0xA0), 1, wxPENSTYLE_SHORT_DASH);
m_penDotDash = wxPen(wxColor(0xD0, 0xD0, 0xD0), 1, wxPENSTYLE_DOT_DASH);
m_penSolid = wxPen(wxColor(0x00, 0x00, 0x00), 1, wxPENSTYLE_SOLID);
SetBackgroundStyle(wxBG_STYLE_PAINT);
SetLabelSize(10.0);
}
//-------------------------------------------------------------------------
// ~PlotPanel()
//-------------------------------------------------------------------------
PlotPanel::~PlotPanel()
{
if(m_pBmp != NULL)
{
delete m_pBmp;
}
}
//-------------------------------------------------------------------------
// GetLabelSize()
//-------------------------------------------------------------------------
double PlotPanel::GetLabelSize()
{
return m_label_size;
}
//-------------------------------------------------------------------------
// SetLabelSize()
//-------------------------------------------------------------------------
void PlotPanel::SetLabelSize(double size)
{
m_label_size = size;
}
//-------------------------------------------------------------------------
// OnShow()
//-------------------------------------------------------------------------
void PlotPanel::OnShow(wxShowEvent& event)
{
this->Refresh();
}
//-------------------------------------------------------------------------
// OnErase()
//-------------------------------------------------------------------------
void PlotPanel::OnErase(wxEraseEvent& event)
{
event.Skip();
}
//-------------------------------------------------------------------------
// OnSize()
//-------------------------------------------------------------------------
void PlotPanel::OnSize(wxSizeEvent& event)
{
m_rCtrlPrev = m_rCtrl;
m_rCtrl = GetClientRect();
if(m_use_bitmap)
{
if(!m_oImage.IsOk())
{
m_oImage.Create(m_rCtrl.GetWidth(), m_rCtrl.GetHeight(), true);
}
else
{
m_oImage.Rescale(m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
}
m_pBmp = new wxBitmap(m_oImage, wxBITMAP_SCREEN_DEPTH);
m_firstPass = true;
}
this->Refresh();
}
//-------------------------------------------------------------------------
// OnMouseMove()
//-------------------------------------------------------------------------
void PlotPanel::OnMouseMove(wxMouseEvent& event)
{
// if(m_mouseDown)
// {
// paintNow();
// }
}
//-------------------------------------------------------------------------
// OnMouseLeftDown()
//-------------------------------------------------------------------------
void PlotPanel::OnMouseLeftDown(wxMouseEvent& event)
{
}
//-------------------------------------------------------------------------
// OnMouseRightDown()
//-------------------------------------------------------------------------
void PlotPanel::OnMouseRightDown(wxMouseEvent& event)
{
}
//-------------------------------------------------------------------------
// OnMouseWheelMoved()
//-------------------------------------------------------------------------
void PlotPanel::OnMouseWheelMoved(wxMouseEvent& event)
{
}
//-------------------------------------------------------------------------
// OnMouseLeftUp()
//-------------------------------------------------------------------------
void PlotPanel::OnMouseLeftUp(wxMouseEvent& event)
{
m_mouseDown = false;
}
//-------------------------------------------------------------------------
// SetZoomFactor()
//-------------------------------------------------------------------------
double PlotPanel::SetZoomFactor(double zf)
{
if((zf > 0) && (zf < 5.0))
{
m_zoomFactor = zf;
}
return zf;
}
//-------------------------------------------------------------------------
// GetZoomFactor()
//-------------------------------------------------------------------------
double PlotPanel::GetZoomFactor(double zf)
{
return m_zoomFactor;
}
//-------------------------------------------------------------------------
// draw()
//-------------------------------------------------------------------------
void PlotPanel::draw(wxAutoBufferedPaintDC& pDC)
{
printf("PlotPanel::draw()");
wxMemoryDC m_mDC;
m_mDC.SelectObject(*m_pBmp);
m_rCtrl = GetClientRect();
m_rGrid = m_rCtrl;
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
m_rGrid.Offset(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
pDC.Clear();
m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
if(m_firstPass)
{
m_firstPass = false;
m_mDC.FloodFill(0, 0, VERY_LTGREY_COLOR);
// Draw a filled rectangle with aborder
wxBrush ltGraphBkgBrush = wxBrush(DARK_BLUE_COLOR);
m_mDC.SetBrush(ltGraphBkgBrush);
m_mDC.SetPen(wxPen(BLACK_COLOR, 0));
m_mDC.DrawRectangle(m_rPlot);
}
if(m_newdata)
{
m_newdata = false;
int t = m_rPlot.GetTop();
int l = m_rPlot.GetLeft();
// int r = m_rPlot.GetRight();
int h = m_rPlot.GetHeight();
int w = m_rPlot.GetWidth();
pDC.Blit(l, t, w, h, &m_mDC, l, t);
}
drawGraticule(pDC);
m_mDC.SetBrush(wxNullBrush);
m_mDC.SelectObject(wxNullBitmap);
}
//-------------------------------------------------------------------------
// drawGraticule()
//-------------------------------------------------------------------------
void PlotPanel::drawGraticule(wxAutoBufferedPaintDC& pDC)
{
int p;
char buf[15];
wxString s;
// Vertical gridlines
pDC.SetPen(m_penShortDash);
for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < ((m_rGrid.GetWidth() - XLEFT_OFFSET) + GRID_INCREMENT); p += GRID_INCREMENT)
{
pDC.DrawLine(p, (m_rGrid.GetHeight() + PLOT_BORDER), p, PLOT_BORDER);
}
// Horizontal gridlines
pDC.SetPen(m_penDotDash);
for(p = (m_rGrid.GetHeight() - GRID_INCREMENT); p > PLOT_BORDER; p -= GRID_INCREMENT)
{
pDC.DrawLine(PLOT_BORDER + XLEFT_OFFSET, (p + PLOT_BORDER), (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), (p + PLOT_BORDER));
}
// Label the X-Axis
pDC.SetPen(wxPen(GREY_COLOR, 1));
for(p = GRID_INCREMENT; p < (m_rGrid.GetWidth() - YBOTTOM_OFFSET); p += GRID_INCREMENT)
{
sprintf(buf, "%1.1f Hz",(double)(p / 10));
pDC.DrawText(buf, p - PLOT_BORDER + XLEFT_OFFSET, m_rGrid.GetHeight() + YBOTTOM_OFFSET/2);
}
// Label the Y-Axis
//for(p = GRID_INCREMENT; p < (h - YBOTTOM_OFFSET); p += GRID_INCREMENT)
for(p = (m_rGrid.GetHeight() - GRID_INCREMENT); p > PLOT_BORDER; p -= GRID_INCREMENT)
{
sprintf(buf, "%1.0f", (double)((m_rGrid.GetHeight() - p) * -10));
pDC.DrawText(buf, XLEFT_TEXT_OFFSET, p);
}
}
//-------------------------------------------------------------------------
// paintEvent()
//
// Called by the system of by wxWidgets when the panel needs
// to be redrawn. You can also trigger this call by calling
// Refresh()/Update().
//-------------------------------------------------------------------------
void PlotPanel::OnPaint(wxPaintEvent & evt)
{
wxAutoBufferedPaintDC pdc(this);
draw(pdc);
}

150
src/fdmdv2_plot.h 100644
View File

@ -0,0 +1,150 @@
//==========================================================================
// Name: fdmdv2_plot.h
// Purpose: Declares simple wxWidgets application with GUI
// Created: Apr. 10, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
//#include "fdmdv2_main.h"
#ifndef __FDMDV2_PLOT__
#define __FDMDV2_PLOT__
#include <wx/wx.h>
#include <wx/aui/auibook.h>
#include <wx/rawbmp.h>
#include <wx/image.h>
#include <wx/dcbuffer.h>
#define MAX_ZOOM 7
#define MAX_BMP_X (400 * MAX_ZOOM)
#define MAX_BMP_Y (400 * MAX_ZOOM)
#define DATA_LINE_HEIGHT 10
#define TEXT_BASELINE_OFFSET_Y -5
#define wxUSE_FILEDLG 1
#define wxUSE_LIBPNG 1
#define wxUSE_LIBJPEG 1
#define wxUSE_GIF 1
#define wxUSE_PCX 1
#define wxUSE_LIBTIFF 1
#define PLOT_BORDER 12
#define XLEFT_OFFSET 40
#define XLEFT_TEXT_OFFSET 6
#define YBOTTOM_OFFSET 20
#define YBOTTOM_TEXT_OFFSET 15
#define GRID_INCREMENT 50
#define BLACK_COLOR wxColor(0x00, 0x00, 0x00)
#define GREY_COLOR wxColor(0x80, 0x80, 0x80)
#define DARK_GREY_COLOR wxColor(0x40, 0x40, 0x40)
#define MEDIUM_GREY_COLOR wxColor(0xC0, 0xC0, 0xC0)
#define LIGHT_GREY_COLOR wxColor(0xE0, 0xE0, 0xE0)
#define VERY_LTGREY_COLOR wxColor(0xF8, 0xF8, 0xF8)
#define WHITE_COLOR wxColor(0xFF, 0xFF, 0xFF)
#define DARK_BLUE_COLOR wxColor(0x00, 0x00, 0x60)
#define BLUE_COLOR wxColor(0x00, 0x00, 0xFF)
#define LIGHT_BLUE_COLOR wxColor(0x80, 0x80, 0xFF)
#define RED_COLOR wxColor(0xFF, 0x5E, 0x5E)
#define LIGHT_RED_COLOR wxColor(0xFF, 0xE0, 0xE0)
#define DARK_RED_COLOR wxColor(0xFF, 0x00, 0x00)
#define PINK_COLOR wxColor(0xFF, 0x80, 0xFF)
#define LIGHT_GREEN_COLOR wxColor(0xE3, 0xFF, 0xE0)
#define GREEN_COLOR wxColor(0x95, 0xFF, 0x8A)
#define DARK_GREEN_COLOR wxColor(0x20, 0xFF, 0x08)
#define VERY_GREEN_COLOR wxColor(0x00, 0xFF, 0x00)
#define YELLOW_COLOR wxColor(0xFF, 0xFF, 0x5E)
#define LIGHT_YELLOW_COLOR wxColor(0xFF, 0xFF, 0xB5)
#define DARK_YELLOW_COLOR wxColor(0xFF, 0xFF, 0x08)
class MainFrame;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotPanel
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class PlotPanel : public wxPanel
{
public:
PlotPanel(wxFrame* parent);
~PlotPanel();
wxPen m_penShortDash;
wxPen m_penDotDash;
wxPen m_penSolid;
wxRect m_rCtrlPrev;
wxRect m_rCtrl;
wxRect m_rGrid;
wxRect m_rPlot;
MainFrame *m_pTopFrame;
wxAuiNotebook *m_pNoteBook;
double m_label_size;
wxSize m_Bufsz;
bool m_newdata;
wxImage m_oImage;
wxBitmap *m_pBmp;
wxNativePixelData *m_pPix;
// some useful events
void OnMouseMove(wxMouseEvent& event);
virtual void OnMouseLeftDown(wxMouseEvent& event);
void OnMouseLeftUp(wxMouseEvent& event);
virtual void OnMouseRightDown(wxMouseEvent& event);
void OnMouseWheelMoved(wxMouseEvent& event);
void OnClose(wxCloseEvent& event ){ event.Skip(); }
void OnSize( wxSizeEvent& event );
void OnErase(wxEraseEvent& event);
void OnPaint(wxPaintEvent& event);
//void OnUpdateUI( wxUpdateUIEvent& event ){ event.Skip(); }
void paintEvent(wxPaintEvent & evt);
virtual void draw(wxAutoBufferedPaintDC& pdc);
virtual void drawGraticule(wxAutoBufferedPaintDC& pdc);
virtual double SetZoomFactor(double zf);
virtual double GetZoomFactor(double zf);
virtual void OnShow(wxShowEvent& event);
virtual double GetLabelSize();
virtual void SetLabelSize(double size);
protected:
int m_x;
int m_y;
int m_left;
int m_top;
int m_prev_w;
int m_prev_h;
int m_prev_x;
int m_prev_y;
bool m_use_bitmap;
bool m_clip;
bool m_rubberBand;
bool m_mouseDown;
bool m_firstPass;
double m_zoomFactor;
int m_greyscale;
int m_line_color;
DECLARE_EVENT_TABLE()
};
#endif //__FDMDV2_PLOT__

View File

@ -0,0 +1,281 @@
//==========================================================================
// Name: fdmdv2_plot_scalar.cpp
// Purpose: Plots scalar amplitude against time
// Created: June 22, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <string.h>
#include "wx/wx.h"
#include "fdmdv2_main.h"
#include "fdmdv2_plot_scalar.h"
BEGIN_EVENT_TABLE(PlotScalar, PlotPanel)
EVT_PAINT (PlotScalar::OnPaint)
EVT_MOTION (PlotScalar::OnMouseMove)
EVT_MOUSEWHEEL (PlotScalar::OnMouseWheelMoved)
EVT_SIZE (PlotScalar::OnSize)
EVT_SHOW (PlotScalar::OnShow)
// EVT_ERASE_BACKGROUND(PlotScalar::OnErase)
END_EVENT_TABLE()
//----------------------------------------------------------------
// PlotScalar()
//----------------------------------------------------------------
PlotScalar::PlotScalar(wxFrame* parent,
int channels, // number on channels to plot
float t_secs, // time covered by entire x axis in seconds
float sample_period_secs, // time between each sample in seconds
float a_min, // min ampltude of samples being plotted
float a_max, // max ampltude of samples being plotted
float graticule_t_step, // time step of x (time) axis graticule in seconds
float graticule_a_step, // step of amplitude axis graticule
const char a_fmt[], // printf format string for amplitude axis labels
int mini // true for mini-plot - don't draw graticule
): PlotPanel(parent)
{
int i;
m_rCtrl = GetClientRect();
m_channels = channels;
m_t_secs = t_secs;
m_sample_period_secs = sample_period_secs;
m_a_min = a_min;
m_a_max = a_max;
m_graticule_t_step = graticule_t_step;
m_graticule_a_step = graticule_a_step;
assert(strlen(a_fmt) < 15);
strcpy(m_a_fmt, a_fmt);
m_mini = mini;
// work out number of samples we will store and allocate storage
m_samples = m_t_secs/m_sample_period_secs;
m_mem = new float[m_samples*m_channels];
for(i = 0; i < m_samples*m_channels; i++)
{
m_mem[i] = 0.0;
}
}
//----------------------------------------------------------------
// ~PlotScalar()
//----------------------------------------------------------------
PlotScalar::~PlotScalar()
{
delete m_mem;
}
//----------------------------------------------------------------
// add_new_sample()
//----------------------------------------------------------------
void PlotScalar::add_new_sample(int channel, float sample)
{
int i;
int offset = channel*m_samples;
assert(channel < m_channels);
for(i = 0; i < m_samples-1; i++)
{
m_mem[offset+i] = m_mem[offset+i+1];
}
m_mem[offset+m_samples-1] = sample;
}
//----------------------------------------------------------------
// add_new_samples()
//----------------------------------------------------------------
void PlotScalar::add_new_short_samples(int channel, short samples[], int length, float scale_factor)
{
int i;
int offset = channel*m_samples;
assert(channel < m_channels);
for(i = 0; i < m_samples-length; i++)
m_mem[offset+i] = m_mem[offset+i+length];
for(; i < m_samples; i++)
m_mem[offset+i] = (float)*samples++/scale_factor;
}
//----------------------------------------------------------------
// draw()
//----------------------------------------------------------------
void PlotScalar::draw(wxAutoBufferedPaintDC& dc)
{
float index_to_px;
float a_to_py;
int i;
int x, y;
int prev_x, prev_y;
float a;
m_rCtrl = GetClientRect();
m_rGrid = m_rCtrl;
if (!m_mini)
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
//printf("h %d w %d\n", m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
//printf("h %d w %d\n", m_rGrid.GetWidth(), m_rGrid.GetHeight());
// black background
dc.Clear();
if (m_mini)
m_rPlot = wxRect(0, 0, m_rGrid.GetWidth(), m_rGrid.GetHeight());
else
m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 0));
dc.DrawRectangle(m_rPlot);
index_to_px = (float)m_rGrid.GetWidth()/m_samples;
a_to_py = (float)m_rGrid.GetHeight()/(m_a_max - m_a_min);
wxPen pen;
pen.SetColour(DARK_GREEN_COLOR);
pen.SetWidth(1);
dc.SetPen(pen);
// draw all samples
prev_x = prev_y = 0; // stop warning
// plot each channel
int offset;
for(offset=0; offset<m_channels*m_samples; offset+=m_samples) {
for(i = 0; i < m_samples; i++) {
x = index_to_px * i;
a = m_mem[offset+i];
if (a < m_a_min) a = m_a_min;
if (a > m_a_max) a = m_a_max;
// invert y axis and offset by minimum
y = m_rGrid.GetHeight() - a_to_py * a + m_a_min*a_to_py;
// put inside plot window
if (!m_mini) {
x += PLOT_BORDER + XLEFT_OFFSET;
y += PLOT_BORDER;
}
if (i)
dc.DrawLine(x, y, prev_x, prev_y);
prev_x = x; prev_y = y;
}
}
drawGraticule(dc);
}
//-------------------------------------------------------------------------
// drawGraticule()
//-------------------------------------------------------------------------
void PlotScalar::drawGraticule(wxAutoBufferedPaintDC& dc)
{
float t, a;
int x, y, text_w, text_h;
char buf[15];
wxString s;
float sec_to_px;
float a_to_py;
wxBrush ltGraphBkgBrush;
ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
ltGraphBkgBrush.SetColour(*wxBLACK);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 1));
sec_to_px = (float)m_rGrid.GetWidth()/m_t_secs;
a_to_py = (float)m_rGrid.GetHeight()/(m_a_max - m_a_min);
// upper LH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER)
// lower RH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET + m_rGrid.GetWidth(),
// PLOT_BORDER + m_rGrid.GetHeight())
// Vertical gridlines
dc.SetPen(m_penShortDash);
for(t=0; t<=m_t_secs; t+=m_graticule_t_step) {
x = t*sec_to_px;
if (m_mini) {
dc.DrawLine(x, m_rGrid.GetHeight(), x, 0);
}
else {
x += PLOT_BORDER + XLEFT_OFFSET;
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
}
if (!m_mini) {
sprintf(buf, "%2.1fs", t);
GetTextExtent(buf, &text_w, &text_h);
dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
}
}
// Horizontal gridlines
dc.SetPen(m_penDotDash);
for(a=m_a_min; a<m_a_max; a+=m_graticule_a_step) {
y = m_rGrid.GetHeight() - a*a_to_py + m_a_min*a_to_py;
if (m_mini) {
dc.DrawLine(0, y, m_rGrid.GetWidth(), y);
}
else {
y += PLOT_BORDER;
dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
(m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
}
if (!m_mini) {
sprintf(buf, m_a_fmt, a);
GetTextExtent(buf, &text_w, &text_h);
dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
}
}
}
//----------------------------------------------------------------
// OnPaint()
//----------------------------------------------------------------
void PlotScalar::OnPaint(wxPaintEvent& event)
{
wxAutoBufferedPaintDC dc(this);
draw(dc);
}
//----------------------------------------------------------------
// OnSize()
//----------------------------------------------------------------
void PlotScalar::OnSize(wxSizeEvent& event)
{
}
//----------------------------------------------------------------
// OnShow()
//----------------------------------------------------------------
void PlotScalar::OnShow(wxShowEvent& event)
{
}

View File

@ -0,0 +1,73 @@
//==========================================================================
// Name: fdmdv2_plot_scalar.h
// Purpose: Defines a scalar plot derivative of fdmdv2_plot.
// Created: June 22, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_PLOT_SCALAR__
#define __FDMDV2_PLOT_SCALAR__
#include "fdmdv2_plot.h"
#include "fdmdv2_defines.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotScalar
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class PlotScalar: public PlotPanel
{
public:
PlotScalar(wxFrame* parent,
int channels,
float t_secs,
float sample_period_secs,
float a_min,
float a_max,
float graticule_t_step,
float graticule_a_step,
const char a_fmt[],
int mini
);
~PlotScalar();
void add_new_sample(int channel, float sample);
void add_new_short_samples(int channel, short samples[], int length, float scale_factor);
protected:
int m_channels;
float m_t_secs;
float m_sample_period_secs;
float m_a_min;
float m_a_max;
float m_graticule_t_step;
float m_graticule_a_step;
char m_a_fmt[15];
int m_mini;
int m_samples;
float *m_mem;
void draw(wxAutoBufferedPaintDC& dc);
void drawGraticule(wxAutoBufferedPaintDC& dc);
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
void OnShow(wxShowEvent& event);
DECLARE_EVENT_TABLE()
};
#endif // __FDMDV2_PLOT_SCALAR__

View File

@ -0,0 +1,199 @@
//==========================================================================
// Name: fdmdv2_plot_scatter.cpp
// Purpose: A scatter plot derivative of fdmdv2_plot.
// Created: June 24, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <string.h>
#include "wx/wx.h"
#include "fdmdv2_plot_scatter.h"
BEGIN_EVENT_TABLE(PlotScatter, PlotPanel)
EVT_PAINT (PlotScatter::OnPaint)
EVT_MOTION (PlotScatter::OnMouseMove)
EVT_MOUSEWHEEL (PlotScatter::OnMouseWheelMoved)
EVT_SIZE (PlotScatter::OnSize)
EVT_SHOW (PlotScatter::OnShow)
// EVT_ERASE_BACKGROUND(PlotScatter::OnErase)
END_EVENT_TABLE()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// PlotScatter
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PlotScatter::PlotScatter(wxFrame* parent) : PlotPanel(parent)
{
int i;
for(i=0; i < SCATTER_MEM_SYMS_MAX; i++)
{
m_mem[i].real = 0.0;
m_mem[i].imag = 0.0;
}
m_filter_max_xy = 0.1;
// defaults so we start off with something sensible
Nsym = 14+1;
scatterMemSyms = ((int)(SCATTER_MEM_SECS*(Nsym/DT)));
assert(scatterMemSyms <= SCATTER_MEM_SYMS_MAX);
}
// changing number of carriers changes number of symbols to plot
void PlotScatter::setNc(int Nc) {
Nsym = Nc+1;
assert(Nsym <= (FDMDV_NC_MAX+1));
scatterMemSyms = ((int)(SCATTER_MEM_SECS*(Nsym/DT)));
assert(scatterMemSyms <= SCATTER_MEM_SYMS_MAX);
}
//----------------------------------------------------------------
// draw()
//----------------------------------------------------------------
void PlotScatter::draw(wxAutoBufferedPaintDC& dc)
{
float x_scale;
float y_scale;
int i;
int x;
int y;
wxColour sym_to_colour[] = {wxColor(0,0,255),
wxColor(0,255,0),
wxColor(0,255,255),
wxColor(255,0,0),
wxColor(255,0,255),
wxColor(255,255,0),
wxColor(255,255,255),
wxColor(0,0,255),
wxColor(0,255,0),
wxColor(0,255,255),
wxColor(255,0,0),
wxColor(255,0,255),
wxColor(255,255,0),
wxColor(255,255,255),
wxColor(0,0,255),
wxColor(0,255,0),
wxColor(0,255,255),
wxColor(255,0,0),
wxColor(255,0,255)
};
m_rCtrl = GetClientRect();
m_rGrid = m_rCtrl;
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
// black background
dc.Clear();
m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 0));
dc.DrawRectangle(m_rPlot);
wxPen pen;
pen.SetWidth(1); // note this is ignored by DrawPoint
// automatically scale, first measure the maximum value
float max_xy = 1E-12;
float real,imag;
for(i=0; i< scatterMemSyms; i++) {
real = fabs(m_mem[i].real);
imag = fabs(m_mem[i].imag);
if (real > max_xy)
max_xy = real;
if (imag > max_xy)
max_xy = imag;
}
// smooth it out and set a lower limit to prevent didev by 0 issues
m_filter_max_xy = BETA*m_filter_max_xy + (1 - BETA)*2.5*max_xy;
if (m_filter_max_xy < 0.001)
m_filter_max_xy = 0.001;
// quantise to log steps to prevent scatter scaling bobbing about too
// much as scaling varies
float quant_m_filter_max_xy = exp(floor(0.5+log(m_filter_max_xy)));
//printf("max_xy: %f m_filter_max_xy: %f quant_m_filter_max_xy: %f\n", max_xy, m_filter_max_xy, quant_m_filter_max_xy);
x_scale = (float)m_rGrid.GetWidth()/quant_m_filter_max_xy;
y_scale = (float)m_rGrid.GetHeight()/quant_m_filter_max_xy;
// draw all samples
for(i = 0; i < scatterMemSyms; i++)
{
x = x_scale * m_mem[i].real + m_rGrid.GetWidth()/2;
y = y_scale * m_mem[i].imag + m_rGrid.GetHeight()/2;
x += PLOT_BORDER + XLEFT_OFFSET;
y += PLOT_BORDER;
pen.SetColour(sym_to_colour[i%Nsym]);
dc.SetPen(pen);
dc.DrawPoint(x, y);
}
}
//----------------------------------------------------------------
// add_new_samples()
//----------------------------------------------------------------
void PlotScatter::add_new_samples(COMP samples[])
{
int i,j;
// shift memory
for(i = 0; i < scatterMemSyms - Nsym; i++)
{
m_mem[i] = m_mem[i+Nsym];
}
// new samples
for(j=0; i < scatterMemSyms; i++,j++)
{
m_mem[i] = samples[j];
}
}
//----------------------------------------------------------------
// OnPaint()
//----------------------------------------------------------------
void PlotScatter::OnPaint(wxPaintEvent& event)
{
wxAutoBufferedPaintDC dc(this);
draw(dc);
}
//----------------------------------------------------------------
// OnSize()
//----------------------------------------------------------------
void PlotScatter::OnSize(wxSizeEvent& event)
{
// todo: clear screen
}
//----------------------------------------------------------------
// OnShow()
//----------------------------------------------------------------
void PlotScatter::OnShow(wxShowEvent& event)
{
}

View File

@ -0,0 +1,56 @@
//==========================================================================
// Name: fdmdv2_plot_scatter.h
// Purpose: A scatter plot derivative of fdmdv2_plot.
// Created: June 24, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_PLOT_SCATTER__
#define __FDMDV2_PLOT_SCATTER__
#include "comp.h"
#include "fdmdv2_plot.h"
#include "fdmdv2_defines.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotScatter
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class PlotScatter : public PlotPanel
{
public:
PlotScatter(wxFrame* parent);
~PlotScatter(){};
void add_new_samples(COMP samples[]);
void setNc(int Nc);
protected:
COMP m_mem[SCATTER_MEM_SYMS_MAX];
COMP m_new_samples[FDMDV_NC_MAX+1];
void draw(wxAutoBufferedPaintDC& dc);
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
void OnShow(wxShowEvent& event);
DECLARE_EVENT_TABLE()
private:
int Nsym;
int scatterMemSyms;
float m_filter_max_xy;
};
#endif //__FDMDV2_PLOT_SCATTER__

View File

@ -0,0 +1,266 @@
//==========================================================================
// Name: fdmdv2_plot_waterfall.cpp
// Purpose: Implements a waterfall plot derivative of fdmdv2_plot.
// Created: June 23, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <string.h>
#include "wx/wx.h"
#include "fdmdv2_main.h"
extern float g_avmag[]; // average mag data passed to draw()
void fdmdv2_clickTune(float frequency); // callback to pass new click freq
BEGIN_EVENT_TABLE(PlotSpectrum, PlotPanel)
EVT_MOTION (PlotSpectrum::OnMouseMove)
EVT_LEFT_DOWN (PlotSpectrum::OnMouseLeftDown)
EVT_LEFT_UP (PlotSpectrum::OnMouseLeftUp)
EVT_MOUSEWHEEL (PlotSpectrum::OnMouseWheelMoved)
EVT_PAINT (PlotSpectrum::OnPaint)
EVT_SHOW (PlotSpectrum::OnShow)
END_EVENT_TABLE()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotSpectrum
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PlotSpectrum::PlotSpectrum(wxFrame* parent, float *magdB, int n_magdB,
float min_mag_db, float max_mag_db, bool clickTune): PlotPanel(parent)
{
m_greyscale = 0;
m_Bufsz = GetMaxClientSize();
m_newdata = false;
m_firstPass = true;
m_line_color = 0;
SetLabelSize(10.0);
m_magdB = magdB;
m_n_magdB = n_magdB; // number of points in magdB that covers 0 ... MAX_F_HZ of spectrum
m_max_mag_db = max_mag_db;
m_min_mag_db = min_mag_db;
m_rxFreq = 0.0;
m_clickTune = clickTune;
}
//----------------------------------------------------------------
// ~PlotSpectrum()
//----------------------------------------------------------------
PlotSpectrum::~PlotSpectrum()
{
}
//----------------------------------------------------------------
// OnSize()
//----------------------------------------------------------------
void PlotSpectrum::OnSize(wxSizeEvent& event) {
}
//----------------------------------------------------------------
// OnPaint()
//----------------------------------------------------------------
void PlotSpectrum::OnPaint(wxPaintEvent& event)
{
wxAutoBufferedPaintDC dc(this);
draw(dc);
}
//----------------------------------------------------------------
// OnShow()
//----------------------------------------------------------------
void PlotSpectrum::OnShow(wxShowEvent& event)
{
}
//----------------------------------------------------------------
// draw()
//----------------------------------------------------------------
void PlotSpectrum::draw(wxAutoBufferedPaintDC& dc)
{
m_rCtrl = GetClientRect();
// m_rGrid is coords of inner window we actually plot to. We deflate it a bit
// to leave room for axis labels. We need to work this out every time we draw
// as OnSize() may not be called before OnPaint(), for example when a new tab
// is selected
m_rGrid = m_rCtrl;
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
dc.Clear();
// black background
m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 0));
dc.DrawRectangle(m_rPlot);
// draw spectrum
int x, y, prev_x, prev_y, index;
float index_to_px, mag_dB_to_py, mag;
m_newdata = false;
wxPen pen;
pen.SetColour(DARK_GREEN_COLOR);
pen.SetWidth(1);
dc.SetPen(pen);
index_to_px = (float)m_rGrid.GetWidth()/m_n_magdB;
mag_dB_to_py = (float)m_rGrid.GetHeight()/(m_max_mag_db - m_min_mag_db);
prev_x = PLOT_BORDER + XLEFT_OFFSET;
prev_y = PLOT_BORDER;
for(index = 0; index < m_n_magdB; index++)
{
x = index*index_to_px;
mag = m_magdB[index];
if (mag > m_max_mag_db) mag = m_max_mag_db;
if (mag < m_min_mag_db) mag = m_min_mag_db;
y = -(mag - m_max_mag_db) * mag_dB_to_py;
x += PLOT_BORDER + XLEFT_OFFSET;
y += PLOT_BORDER;
if (index)
dc.DrawLine(x, y, prev_x, prev_y);
prev_x = x; prev_y = y;
}
// and finally draw Graticule
drawGraticule(dc);
}
//-------------------------------------------------------------------------
// drawGraticule()
//-------------------------------------------------------------------------
void PlotSpectrum::drawGraticule(wxAutoBufferedPaintDC& dc)
{
int x, y, text_w, text_h;
char buf[15];
wxString s;
float f, mag, freq_hz_to_px, mag_dB_to_py;
wxBrush ltGraphBkgBrush;
ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
ltGraphBkgBrush.SetColour(*wxBLACK);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 1));
freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ);
mag_dB_to_py = (float)m_rGrid.GetHeight()/(m_max_mag_db - m_min_mag_db);
// upper LH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER)
// lower RH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET + m_rGrid.GetWidth(),
// PLOT_BORDER + m_rGrid.GetHeight())
// Check if small screen size means text will overlap
int textXStep = STEP_F_HZ*freq_hz_to_px;
int textYStep = STEP_MAG_DB*mag_dB_to_py;
sprintf(buf, "%4.0fHz", (float)MAX_F_HZ - STEP_F_HZ);
GetTextExtent(buf, &text_w, &text_h);
int overlappedText = (text_w > textXStep) || (text_h > textYStep);
//printf("text_w: %d textXStep: %d text_h: %d textYStep: %d overlappedText: %d\n", text_w, textXStep,
// text_h, textYStep, overlappedText);
// Vertical gridlines
for(f=STEP_F_HZ; f<MAX_F_HZ; f+=STEP_F_HZ) {
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
dc.SetPen(m_penShortDash);
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
dc.SetPen(wxPen(BLACK_COLOR, 1));
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
sprintf(buf, "%4.0fHz", f);
GetTextExtent(buf, &text_w, &text_h);
if (!overlappedText)
dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
}
dc.SetPen(wxPen(BLACK_COLOR, 1));
for(f=STEP_MINOR_F_HZ; f<MAX_F_HZ; f+=STEP_MINOR_F_HZ)
{
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET-5);
}
// Horizontal gridlines
dc.SetPen(m_penDotDash);
for(mag=m_min_mag_db; mag<=m_max_mag_db; mag+=STEP_MAG_DB) {
y = -(mag - m_max_mag_db) * mag_dB_to_py;
y += PLOT_BORDER;
dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
(m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
sprintf(buf, "%3.0fdB", mag);
GetTextExtent(buf, &text_w, &text_h);
if (!overlappedText)
dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
}
// red rx tuning line
if (m_rxFreq != 0.0) {
dc.SetPen(wxPen(RED_COLOR, 2));
x = m_rxFreq*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
//printf("m_rxFreq %f x %d\n", m_rxFreq, x);
dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rCtrl.GetHeight());
}
}
//-------------------------------------------------------------------------
// OnMouseDown()
//-------------------------------------------------------------------------
void PlotSpectrum::OnMouseLeftDown(wxMouseEvent& event)
{
m_mouseDown = true;
wxClientDC dc(this);
wxPoint pt(event.GetLogicalPosition(dc));
// map x coord to edges of actual plot
pt.x -= PLOT_BORDER + XLEFT_OFFSET;
pt.y -= PLOT_BORDER;
// valid click if inside of plot
if ((pt.x >= 0) && (pt.x <= m_rGrid.GetWidth()) && (pt.y >=0) && m_clickTune) {
float freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ);
float clickFreq = (float)pt.x/freq_hz_to_px;
// see PlotWaterfall::OnMouseDown()
fdmdv2_clickTune(clickFreq);
}
}

View File

@ -0,0 +1,58 @@
//==========================================================================
// Name: fdmdv2_plot_spectrum.h
// Purpose: Defines a spectrum plot derived from fdmdv2_plot class.
// Created: June 22, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_PLOT_SPECTRUM__
#define __FDMDV2_PLOT_SPECTRUM__
#include "fdmdv2_plot.h"
#include "fdmdv2_defines.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class Waterfall
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class PlotSpectrum : public PlotPanel
{
public:
PlotSpectrum(wxFrame* parent, float *magdB, int n_magdB,
float min_mag_db=MIN_MAG_DB, float max_mag_db=MAX_MAG_DB, bool clickTune=true);
~PlotSpectrum();
void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; }
void setFreqScale(int n_magdB) { m_n_magdB = n_magdB; }
protected:
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
void OnShow(wxShowEvent& event);
void drawGraticule(wxAutoBufferedPaintDC& dc);
void draw(wxAutoBufferedPaintDC& dc);
void OnMouseLeftDown(wxMouseEvent& event);
private:
float m_rxFreq;
float m_max_mag_db;
float m_min_mag_db;
float *m_magdB;
int m_n_magdB;
bool m_clickTune;
DECLARE_EVENT_TABLE()
};
#endif //__FDMDV2_PLOT_SPECTRUM__

View File

@ -0,0 +1,483 @@
//==========================================================================
// Name: fdmdv2_plot_waterfall.cpp
// Purpose: Implements a waterfall plot derivative of fdmdv2_plot.
// Created: June 22, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <string.h>
#include "wx/wx.h"
#include "fdmdv2_main.h"
extern float g_avmag[]; // av mag spec passed in to draw()
void fdmdv2_clickTune(float frequency); // callback to pass new click freq
BEGIN_EVENT_TABLE(PlotWaterfall, PlotPanel)
EVT_PAINT (PlotWaterfall::OnPaint)
EVT_MOTION (PlotWaterfall::OnMouseMove)
EVT_LEFT_DOWN (PlotWaterfall::OnMouseLeftDown)
EVT_RIGHT_DOWN (PlotWaterfall::OnMouseRightDown)
EVT_LEFT_UP (PlotWaterfall::OnMouseLeftUp)
EVT_MOUSEWHEEL (PlotWaterfall::OnMouseWheelMoved)
EVT_SIZE (PlotWaterfall::OnSize)
EVT_SHOW (PlotWaterfall::OnShow)
END_EVENT_TABLE()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class WaterfallPlot
//
// @class WaterfallPlot
// @author David Witten
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
PlotWaterfall::PlotWaterfall(wxFrame* parent, bool graticule, int colour): PlotPanel(parent)
{
for(int i = 0; i < 255; i++)
{
m_heatmap_lut[i] = heatmap((float)i, 0.0, 255.0);
}
m_graticule = graticule;
m_colour = colour;
m_Bufsz = GetMaxClientSize();
m_newdata = false;
m_firstPass = true;
m_line_color = 0;
m_modem_stats_max_f_hz = MODEM_STATS_MAX_F_HZ;
SetLabelSize(10.0);
m_pBmp = NULL;
m_max_mag = MAX_MAG_DB;
m_min_mag = MIN_MAG_DB;
}
// When the window size gets set we can work outthe size of the window
// we plot in and allocate a bit map of the correct size
void PlotWaterfall::OnSize(wxSizeEvent& event)
{
// resize bit map
delete m_pBmp;
m_rCtrl = GetClientRect();
// m_rGrid is coords of inner window we actually plot to. We deflate it a bit
// to leave room for axis labels.
m_rGrid = m_rCtrl;
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
// we want a bit map the size of m_rGrid
m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24);
m_dT = DT;
}
//----------------------------------------------------------------
// paintEvent()
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
// Called by the system of by wxWidgets when the panel needs
// to be redrawn. You can also trigger this call by calling
// Refresh()/Update().
//----------------------------------------------------------------
void PlotWaterfall::OnPaint(wxPaintEvent & evt)
{
wxAutoBufferedPaintDC dc(this);
draw(dc);
}
//----------------------------------------------------------------
// OnShow()
//----------------------------------------------------------------
void PlotWaterfall::OnShow(wxShowEvent& event)
{
}
//----------------------------------------------------------------
// ~PlotWaterfall()
//----------------------------------------------------------------
PlotWaterfall::~PlotWaterfall()
{
}
//----------------------------------------------------------------
// heatmap()
// map val to a rgb colour
// from http://eddiema.ca/2011/01/21/c-sharp-heatmaps/
//----------------------------------------------------------------
unsigned PlotWaterfall::heatmap(float val, float min, float max)
{
unsigned r = 0;
unsigned g = 0;
unsigned b = 0;
val = (val - min) / (max - min);
if(val <= 0.2)
{
b = (unsigned)((val / 0.2) * 255);
}
else if(val > 0.2 && val <= 0.7)
{
b = (unsigned)((1.0 - ((val - 0.2) / 0.5)) * 255);
}
if(val >= 0.2 && val <= 0.6)
{
g = (unsigned)(((val - 0.2) / 0.4) * 255);
}
else if(val > 0.6 && val <= 0.9)
{
g = (unsigned)((1.0 - ((val - 0.6) / 0.3)) * 255);
}
if(val >= 0.5)
{
r = (unsigned)(((val - 0.5) / 0.5) * 255);
}
//printf("%f %x %x %x\n", val, r, g, b);
return (b << 16) + (g << 8) + r;
}
bool PlotWaterfall::checkDT(void)
{
// Check dY is > 1 pixel before proceeding. For small screens
// and large WATERFALL_SECS_Y we might have less than one
// block per pixel. In this case increase m_dT and perform draw
// less often
float px_per_sec = (float)m_rGrid.GetHeight() / WATERFALL_SECS_Y;
float dy = m_dT * px_per_sec;
if (dy < 1.0) {
m_dT += DT;
return false;
}
else
return true;
}
//----------------------------------------------------------------
// draw()
//----------------------------------------------------------------
void PlotWaterfall::draw(wxAutoBufferedPaintDC& dc)
{
m_rCtrl = GetClientRect();
// m_rGrid is coords of inner window we actually plot to. We deflate it a bit
// to leave room for axis labels.
m_rGrid = m_rCtrl;
m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
if (m_pBmp == NULL)
{
// we want a bit map the size of m_rGrid
m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24);
}
dc.Clear();
if(m_newdata)
{
m_newdata = false;
plotPixelData();
dc.DrawBitmap(*m_pBmp, PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
m_dT = DT;
}
else
{
// no data to plot so just erase to black. Blue looks nicer
// but is same colour as low amplitude signal
// Bug on Linux: When Stop is pressed this code doesn't erase
// the lower 25% of the Waterfall Window
m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 0));
dc.DrawRectangle(m_rPlot);
}
drawGraticule(dc);
}
//-------------------------------------------------------------------------
// drawGraticule()
//-------------------------------------------------------------------------
void PlotWaterfall::drawGraticule(wxAutoBufferedPaintDC& dc)
{
int x, y, text_w, text_h;
char buf[15];
wxString s;
float f, time, freq_hz_to_px, time_s_to_py;
wxBrush ltGraphBkgBrush;
ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
ltGraphBkgBrush.SetColour(*wxBLACK);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 1));
freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ);
time_s_to_py = (float)m_rGrid.GetHeight()/WATERFALL_SECS_Y;
// upper LH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER)
// lower RH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET + m_rGrid.GetWidth(),
// PLOT_BORDER + m_rGrid.GetHeight())
// Check if small screen size means text will overlap
int textXStep = STEP_F_HZ*freq_hz_to_px;
int textYStep = WATERFALL_SECS_STEP*time_s_to_py;
sprintf(buf, "%4.0fHz", (float)MAX_F_HZ - STEP_F_HZ);
GetTextExtent(buf, &text_w, &text_h);
int overlappedText = (text_w > textXStep) || (text_h > textYStep);
// Major Vertical gridlines and legend
//dc.SetPen(m_penShortDash);
for(f=STEP_F_HZ; f<MAX_F_HZ; f+=STEP_F_HZ)
{
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
if (m_graticule)
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
else
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
sprintf(buf, "%4.0fHz", f);
GetTextExtent(buf, &text_w, &text_h);
if (!overlappedText)
dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
}
for(f=STEP_MINOR_F_HZ; f<MAX_F_HZ; f+=STEP_MINOR_F_HZ)
{
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET-5);
}
// Horizontal gridlines
dc.SetPen(m_penDotDash);
for(time=0; time<=WATERFALL_SECS_Y; time+=WATERFALL_SECS_STEP) {
y = m_rGrid.GetHeight() - time*time_s_to_py;
y += PLOT_BORDER;
if (m_graticule)
dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
(m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
sprintf(buf, "%3.0fs", time);
GetTextExtent(buf, &text_w, &text_h);
if (!overlappedText)
dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
}
// red rx tuning line
dc.SetPen(wxPen(RED_COLOR, 2));
x = m_rxFreq*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
//printf("m_rxFreq %f x %d\n", m_rxFreq, x);
dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rCtrl.GetHeight());
}
//-------------------------------------------------------------------------
// plotPixelData()
//-------------------------------------------------------------------------
void PlotWaterfall::plotPixelData()
{
float spec_index_per_px;
float intensity_per_dB;
float px_per_sec;
int index;
float dy;
int dy_blocks;
int b;
int px;
int py;
int intensity;
/*
Design Notes:
The height in pixels represents WATERFALL_SECS_Y of data. Every DT
seconds we get a vector of MODEM_STATS_NSPEC spectrum samples which we use
to update the last row. The height of each row is dy pixels, which
maps to DT seconds. We call each dy high rectangle of pixels a
block.
*/
// determine dy, the height of one "block"
px_per_sec = (float)m_rGrid.GetHeight() / WATERFALL_SECS_Y;
dy = m_dT * px_per_sec;
// number of dy high blocks in spectrogram
dy_blocks = m_rGrid.GetHeight()/ dy;
// update min and max amplitude estimates
float max_mag = MIN_MAG_DB;
int min_fft_bin=((float)200/m_modem_stats_max_f_hz)*MODEM_STATS_NSPEC;
int max_fft_bin=((float)2800/m_modem_stats_max_f_hz)*MODEM_STATS_NSPEC;
for(int i=min_fft_bin; i<max_fft_bin; i++)
{
if (g_avmag[i] > max_mag)
{
max_mag = g_avmag[i];
}
}
m_max_mag = BETA*m_max_mag + (1 - BETA)*max_mag;
m_min_mag = max_mag - 20.0;
//printf("max_mag: %f m_max_mag: %f\n", max_mag, m_max_mag);
//intensity_per_dB = (float)256 /(MAX_MAG_DB - MIN_MAG_DB);
intensity_per_dB = (float)256 /(m_max_mag - m_min_mag);
spec_index_per_px = ((float)(MAX_F_HZ)/(float)m_modem_stats_max_f_hz)*(float)MODEM_STATS_NSPEC / (float) m_rGrid.GetWidth();
/*
printf("h %d w %d px_per_sec %d dy %d dy_blocks %d spec_index_per_px: %f\n",
m_rGrid.GetHeight(), m_rGrid.GetWidth(), px_per_sec,
dy, dy_blocks, spec_index_per_px);
*/
// Shift previous bit map up one row of blocks ----------------------------
wxNativePixelData data(*m_pBmp);
wxNativePixelData::Iterator bitMapStart(data);
wxNativePixelData::Iterator p = bitMapStart;
for(b = 0; b < dy_blocks - 1; b++)
{
wxNativePixelData::Iterator psrc = bitMapStart;
wxNativePixelData::Iterator pdest = bitMapStart;
pdest.OffsetY(data, dy * b);
psrc.OffsetY(data, dy * (b+1));
// copy one line of blocks
for(py = 0; py < dy; py++)
{
wxNativePixelData::Iterator pdestRowStart = pdest;
wxNativePixelData::Iterator psrcRowStart = psrc;
for(px = 0; px < m_rGrid.GetWidth(); px++)
{
pdest.Red() = psrc.Red();
pdest.Green() = psrc.Green();
pdest.Blue() = psrc.Blue();
pdest++;
psrc++;
}
pdest = pdestRowStart;
pdest.OffsetY(data, 1);
psrc = psrcRowStart;
psrc.OffsetY(data, 1);
}
}
// Draw last line of blocks using latest amplitude data ------------------
p = bitMapStart;
p.OffsetY(data, dy *(dy_blocks - 1));
for(py = 0; py < dy; py++)
{
wxNativePixelData::Iterator rowStart = p;
for(px = 0; px < m_rGrid.GetWidth(); px++)
{
index = px * spec_index_per_px;
assert(index < MODEM_STATS_NSPEC);
intensity = intensity_per_dB * (g_avmag[index] - m_min_mag);
if(intensity > 255) intensity = 255;
if (intensity < 0) intensity = 0;
//printf("%d %f %d \n", index, g_avmag[index], intensity);
switch (m_colour) {
case 0:
p.Red() = m_heatmap_lut[intensity] & 0xff;
p.Green() = (m_heatmap_lut[intensity] >> 8) & 0xff;
p.Blue() = (m_heatmap_lut[intensity] >> 16) & 0xff;
break;
case 1:
p.Red() = intensity;
p.Green() = intensity;
p.Blue() = intensity;
break;
case 2:
p.Red() = intensity;
p.Green() = intensity;
if (intensity < 127)
p.Blue() = intensity*2;
else
p.Blue() = 255;
break;
}
++p;
}
p = rowStart;
p.OffsetY(data, 1);
}
}
//-------------------------------------------------------------------------
// OnMouseLeftDown()
//-------------------------------------------------------------------------
void PlotWaterfall::OnMouseLeftDown(wxMouseEvent& event)
{
m_mouseDown = true;
wxClientDC dc(this);
wxPoint pt(event.GetLogicalPosition(dc));
// map x coord to edges of actual plot
pt.x -= PLOT_BORDER + XLEFT_OFFSET;
pt.y -= PLOT_BORDER;
// valid click if inside of plot
if ((pt.x >= 0) && (pt.x <= m_rGrid.GetWidth()) && (pt.y >=0))
{
float freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ);
float clickFreq = (float)pt.x/freq_hz_to_px;
// communicate back to other threads
fdmdv2_clickTune(clickFreq);
}
}
//-------------------------------------------------------------------------
// OnMouseRightDown()
//-------------------------------------------------------------------------
void PlotWaterfall::OnMouseRightDown(wxMouseEvent& event)
{
m_colour++;
if (m_colour == 3)
m_colour = 0;
}

View File

@ -0,0 +1,73 @@
//==========================================================================
// Name: fdmdv2_plot_waterfall.h
// Purpose: Defines a waterfall plot derivative of fdmdv2_plot.
// Created: June 22, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __FDMDV2_PLOT_WATERFALL__
#define __FDMDV2_PLOT_WATERFALL__
#include "fdmdv2_plot.h"
#include "fdmdv2_defines.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// Class PlotWaterfall
//
// @class $(Name)
// @author $(User)
// @date $(Date)
// @file $(CurrentFileName).$(CurrentFileExt)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
class PlotWaterfall : public PlotPanel
{
public:
PlotWaterfall(wxFrame* parent, bool graticule, int colour);
~PlotWaterfall();
bool checkDT(void);
void setGreyscale(bool greyscale) { m_greyscale = greyscale; }
void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; }
void setFs(int fs) { m_modem_stats_max_f_hz = fs/2; }
protected:
unsigned m_heatmap_lut[256];
unsigned heatmap(float val, float min, float max);
void OnPaint(wxPaintEvent & evt);
void OnSize(wxSizeEvent& event);
void OnShow(wxShowEvent& event);
void drawGraticule(wxAutoBufferedPaintDC& dc);
void draw(wxAutoBufferedPaintDC& dc);
void plotPixelData();
void OnMouseLeftDown(wxMouseEvent& event);
void OnMouseRightDown(wxMouseEvent& event);
private:
float m_dT;
float m_rxFreq;
bool m_graticule;
float m_min_mag;
float m_max_mag;
int m_colour;
int m_modem_stats_max_f_hz;
DECLARE_EVENT_TABLE()
};
#endif //__FDMDV2_PLOT_WATERFALL__

127
src/hamlib.cpp 100644
View File

@ -0,0 +1,127 @@
//==========================================================================
// Name: hamlib.cpp
//
// Purpose: Hamlib integration for FreeDV
// Created: May 2013
// Authors: Joel Stanley
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <hamlib.h>
#include <vector>
#include <algorithm>
using namespace std;
typedef std::vector<const struct rig_caps *> riglist_t;
static bool rig_cmp(const struct rig_caps *rig1, const struct rig_caps *rig2);
static int build_list(const struct rig_caps *rig, rig_ptr_t);
Hamlib::Hamlib() : m_rig(NULL) {
/* Stop hamlib from spewing info to stderr. */
rig_set_debug(RIG_DEBUG_NONE);
/* Create sorted list of rigs. */
rig_load_all_backends();
rig_list_foreach(build_list, &m_rigList);
sort(m_rigList.begin(), m_rigList.end(), rig_cmp);
/* Reset debug output. */
rig_set_debug(RIG_DEBUG_VERBOSE);
m_rig = NULL;
}
Hamlib::~Hamlib() {
if(m_rig)
close();
}
static int build_list(const struct rig_caps *rig, rig_ptr_t rigList) {
((riglist_t *)rigList)->push_back(rig);
return 1;
}
static bool rig_cmp(const struct rig_caps *rig1, const struct rig_caps *rig2) {
/* Compare manufacturer. */
int r = strcasecmp(rig1->mfg_name, rig2->mfg_name);
if (r != 0)
return r < 0;
/* Compare model. */
r = strcasecmp(rig1->model_name, rig2->model_name);
if (r != 0)
return r < 0;
/* Compare rig ID. */
return rig1->rig_model < rig2->rig_model;
}
void Hamlib::populateComboBox(wxComboBox *cb) {
riglist_t::const_iterator rig = m_rigList.begin();
for (; rig !=m_rigList.end(); rig++) {
char name[128];
snprintf(name, 128, "%s %s", (*rig)->mfg_name, (*rig)->model_name);
cb->Append(name);
}
}
bool Hamlib::connect(unsigned int rig_index, const char *serial_port) {
/* Look up model from index. */
if (rig_index >= m_rigList.size()) {
return false;
}
printf("rig: %s %s (%d)\n", m_rigList[rig_index]->mfg_name,
m_rigList[rig_index]->model_name, m_rigList[rig_index]->rig_model);
if(m_rig) {
printf("Closing old hamlib instance!\n");
close();
}
/* Initialise, configure and open. */
m_rig = rig_init(m_rigList[rig_index]->rig_model);
/* TODO: Also use baud rate from the screen. */
if (!m_rig)
return false;
token_t token = rig_token_lookup(m_rig, "rig_pathname");
if (rig_set_conf(m_rig, token, serial_port) != RIG_OK) {
return false;
}
if (rig_open(m_rig) == RIG_OK) {
return true;
}
return false;
}
bool Hamlib::ptt(bool press) {
if(!m_rig)
return false;
/* TODO(Joel): make ON_DATA and ON configurable. */
ptt_t on = press ? RIG_PTT_ON : RIG_PTT_OFF;
/* TODO(Joel): what should the VFO option be? */
return rig_set_ptt(m_rig, RIG_VFO_CURR, on) == RIG_OK;
}
void Hamlib::close(void) {
if(m_rig) {
rig_close(m_rig);
rig_cleanup(m_rig);
m_rig = NULL;
}
}

28
src/hamlib.h 100644
View File

@ -0,0 +1,28 @@
#ifndef HAMLIB_H
#define HAMLIB_H
extern "C" {
#include <hamlib/rig.h>
}
#include <wx/combobox.h>
#include <vector>
class Hamlib {
public:
Hamlib();
~Hamlib();
void populateComboBox(wxComboBox *cb);
bool connect(unsigned int rig_index, const char *serial_port);
bool ptt(bool press);
void close(void);
typedef std::vector<const struct rig_caps *> riglist_t;
private:
RIG *m_rig;
/* Sorted list of rigs. */
riglist_t m_rigList;
};
#endif /*HAMLIB_H*/

2608
src/sox.h 100644

File diff suppressed because it is too large Load Diff

129
src/sox_biquad.c 100644
View File

@ -0,0 +1,129 @@
//==========================================================================
// Name: sox_biquad.h
// Purpose: Interface into Sox Biquad filters
// Created: Dec 1, 2012
// Authors: David Rowe
//
// To test:
// $ gcc sox_biquad.c -o sox_biquad -DSOX_BIQUAD_UNITTEST -Wall \
// /path/to/sox-14.4.0/src/.libs/libsox.a -lm -lsndfile
// $ ./sox_biquad
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "sox.h"
#include "sox_biquad.h"
#define N_MAX 1024
int lsx_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf,
sox_sample_t *obuf, size_t *isamp, size_t *osamp);
void sox_biquad_start(void)
{
int r = sox_init();
assert(r == SOX_SUCCESS);
}
void sox_biquad_finish(void)
{
sox_quit();
}
/*
Effect must be implemented by biquads.c in sox, arguments are just
like sox command line, for example:
char *argv[10];
argv[0] = "highpass"; argv[1]="1000"; argc=1;
*/
void *sox_biquad_create(int argc, const char *argv[])
{
int ret;
sox_effect_t *e;
int (*start)(sox_effect_t *); /* function pointer to effect start func */
e = sox_create_effect(sox_find_effect(argv[0])); assert(e != NULL);
ret = sox_effect_options(e, argc, (char * const*)&argv[1]);
assert(ret == SOX_SUCCESS);
start = e->handler.start;
e->in_signal.rate = 8000; /* locked at FS=8000 Hz */
ret = start(e); assert(ret == SOX_SUCCESS);
return (void *)e;
}
void sox_biquad_destroy(void *sbq) {
sox_effect_t *e = (sox_effect_t *)sbq;
free(e);
}
void sox_biquad_filter(void *sbq, short out[], short in[], int n)
{
sox_effect_t *e = (sox_effect_t *)sbq;
sox_sample_t ibuf[N_MAX];
sox_sample_t obuf[N_MAX];
size_t isamp, osamp;
unsigned int clips;
SOX_SAMPLE_LOCALS;
int i;
assert(n <= N_MAX);
clips = 0;
for(i=0; i<n; i++)
ibuf[i] = SOX_SIGNED_16BIT_TO_SAMPLE(in[i], clips);
isamp = osamp = (unsigned int)n;
lsx_biquad_flow(e, ibuf, obuf, &isamp, &osamp);
for(i=0; i<n; i++)
out[i] = SOX_SAMPLE_TO_SIGNED_16BIT(obuf[i], clips);
}
#ifdef SOX_BIQUAD_UNITTEST
#define N 20
int main(void) {
void *sbq;
char *argv[10];
short in[N];
short out[N];
int i, argc;;
for(i=0; i<N; i++)
in[i] = 0;
in[0] = 8000;
sox_biquad_start();
argv[0] = "highpass"; argv[1]="1000"; argc=1;
sbq = sox_biquad_create(argc, argv);
sox_biquad_filter(sbq, out, in, N);
for(i=0; i<N; i++)
printf("%d\n", out[i]);
sox_biquad_destroy(sbq);
sox_biquad_finish();
return 0;
}
#endif

40
src/sox_biquad.h 100644
View File

@ -0,0 +1,40 @@
//==========================================================================
// Name: sox_biquad.h
// Purpose: Interface into Sox Biquad filters
// Created: Dec 1, 2012
// Authors: David Rowe
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __SOX_BIQUAD__
#define __SOX_BIQUAD__
#ifdef __cplusplus
extern "C" {
#endif
void sox_biquad_start(void);
void sox_biquad_finish(void);
void *sox_biquad_create(int argc, const char *argv[]);
void sox_biquad_destroy(void *sbq);
void sox_biquad_filter(void *sbq, short out[], short in[], int n);
#ifdef __cplusplus
}
#endif
#endif

553
src/topFrame.cpp 100644
View File

@ -0,0 +1,553 @@
//==========================================================================
// Name: topFrame.cpp
//
// Purpose: Implements simple wxWidgets application with GUI.
// Created: Apr. 9, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.1,
// as published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#include "topFrame.h"
extern int g_playFileToMicInEventId;
extern int g_recFileFromRadioEventId;
extern int g_playFileFromRadioEventId;
//=========================================================================
// Code that lays out the main application window
//=========================================================================
TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
this->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
this->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
//=====================================================
// Menubar Setup
m_menubarMain = new wxMenuBar(wxMB_DOCKABLE);
file = new wxMenu();
wxMenuItem* m_menuItemOnTop;
m_menuItemOnTop = new wxMenuItem(file, wxID_ANY, wxString(_("On Top")) , _("Always Top Window"), wxITEM_NORMAL);
file->Append(m_menuItemOnTop);
wxMenuItem* m_menuItemExit;
m_menuItemExit = new wxMenuItem(file, ID_EXIT, wxString(_("E&xit")) , _("Exit Program"), wxITEM_NORMAL);
file->Append(m_menuItemExit);
m_menubarMain->Append(file, _("&File"));
tools = new wxMenu();
wxMenuItem* m_menuItemAudio;
m_menuItemAudio = new wxMenuItem(tools, wxID_ANY, wxString(_("&Audio Config")) , wxEmptyString, wxITEM_NORMAL);
tools->Append(m_menuItemAudio);
wxMenuItem* m_menuItemRigCtrlCfg;
m_menuItemRigCtrlCfg = new wxMenuItem(tools, wxID_ANY, wxString(_("&PTT Config")) , wxEmptyString, wxITEM_NORMAL);
tools->Append(m_menuItemRigCtrlCfg);
wxMenuItem* m_menuItemOptions;
m_menuItemOptions = new wxMenuItem(tools, wxID_ANY, wxString(_("Options")) , wxEmptyString, wxITEM_NORMAL);
tools->Append(m_menuItemOptions);
wxMenuItem* m_menuItemFilter;
m_menuItemFilter = new wxMenuItem(tools, wxID_ANY, wxString(_("&Filter")) , wxEmptyString, wxITEM_NORMAL);
tools->Append(m_menuItemFilter);
wxMenuItem* m_menuItemPlayFileToMicIn;
m_menuItemPlayFileToMicIn = new wxMenuItem(tools, wxID_ANY, wxString(_("Start/Stop Play File - Mic In")) , wxEmptyString, wxITEM_NORMAL);
g_playFileToMicInEventId = m_menuItemPlayFileToMicIn->GetId();
tools->Append(m_menuItemPlayFileToMicIn);
wxMenuItem* m_menuItemRecFileFromRadio;
m_menuItemRecFileFromRadio = new wxMenuItem(tools, wxID_ANY, wxString(_("Start/Stop Record File - From Radio")) , wxEmptyString, wxITEM_NORMAL);
g_recFileFromRadioEventId = m_menuItemRecFileFromRadio->GetId();
tools->Append(m_menuItemRecFileFromRadio);
wxMenuItem* m_menuItemPlayFileFromRadio;
m_menuItemPlayFileFromRadio = new wxMenuItem(tools, wxID_ANY, wxString(_("Start/Stop Play File - From Radio")) , wxEmptyString, wxITEM_NORMAL);
g_playFileFromRadioEventId = m_menuItemPlayFileFromRadio->GetId();
tools->Append(m_menuItemPlayFileFromRadio);
m_menubarMain->Append(tools, _("&Tools"));
help = new wxMenu();
wxMenuItem* m_menuItemHelpUpdates;
m_menuItemHelpUpdates = new wxMenuItem(help, wxID_ANY, wxString(_("Check for Updates")) , wxEmptyString, wxITEM_NORMAL);
help->Append(m_menuItemHelpUpdates);
m_menuItemHelpUpdates->Enable(false);
wxMenuItem* m_menuItemAbout;
m_menuItemAbout = new wxMenuItem(help, ID_ABOUT, wxString(_("&About")) , _("About this program"), wxITEM_NORMAL);
help->Append(m_menuItemAbout);
m_menubarMain->Append(help, _("&Help"));
this->SetMenuBar(m_menubarMain);
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer(wxHORIZONTAL);
//=====================================================
// Left side
//=====================================================
wxBoxSizer* leftSizer;
leftSizer = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer* snrSizer;
snrSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("SNR")), wxVERTICAL);
//------------------------------
// S/N ratio Guage (vert. bargraph)
//------------------------------
m_gaugeSNR = new wxGauge(this, wxID_ANY, 25, wxDefaultPosition, wxSize(15,135), wxGA_SMOOTH|wxGA_VERTICAL);
m_gaugeSNR->SetToolTip(_("Displays signal to noise ratio in dB."));
snrSizer->Add(m_gaugeSNR, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 10);
//------------------------------
// Box for S/N ratio (Numeric)
//------------------------------
m_textSNR = new wxStaticText(this, wxID_ANY, wxT(" 0.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
snrSizer->Add(m_textSNR, 0, wxALIGN_CENTER_HORIZONTAL, 1);
//------------------------------
// S/N ratio slow Checkbox
//------------------------------
m_ckboxSNR = new wxCheckBox(this, wxID_ANY, _("Slow"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
m_ckboxSNR->SetToolTip(_("Smooth but slow SNR estimation"));
snrSizer->Add(m_ckboxSNR, 0, wxALIGN_CENTER_HORIZONTAL, 5);
leftSizer->Add(snrSizer, 2, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 1);
//------------------------------
// Sync Indicator box
//------------------------------
wxStaticBoxSizer* sbSizer3_33;
sbSizer3_33 = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Sync")), wxVERTICAL);
m_rbSync = new wxRadioButton( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
m_rbSync->SetForegroundColour( wxColour( 255, 0, 0 ) );
sbSizer3_33->Add(m_rbSync, 0, wxALIGN_CENTER|wxALL, 1);
leftSizer->Add(sbSizer3_33,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// BER Frames box
//------------------------------
wxStaticBoxSizer* sbSizer_ber;
sbSizer_ber = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Bit Error Rate")), wxVERTICAL);
m_BtnBerReset = new wxButton(this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_ber->Add(m_BtnBerReset, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
m_textBits = new wxStaticText(this, wxID_ANY, wxT("Bits: 0"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
sbSizer_ber->Add(m_textBits, 0, wxALIGN_LEFT, 1);
m_textErrors = new wxStaticText(this, wxID_ANY, wxT("Errs: 0"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
sbSizer_ber->Add(m_textErrors, 0, wxALIGN_LEFT, 1);
m_textBER = new wxStaticText(this, wxID_ANY, wxT("BER: 0.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
sbSizer_ber->Add(m_textBER, 0, wxALIGN_LEFT, 1);
leftSizer->Add(sbSizer_ber,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
//------------------------------
// Signal Level(vert. bargraph)
//------------------------------
wxStaticBoxSizer* levelSizer;
levelSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Level")), wxVERTICAL);
m_textLevel = new wxStaticText(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(60,-1), wxALIGN_CENTRE);
m_textLevel->SetForegroundColour(wxColour(255,0,0));
levelSizer->Add(m_textLevel, 0, wxALIGN_LEFT, 1);
m_gaugeLevel = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxSize(15,135), wxGA_SMOOTH|wxGA_VERTICAL);
m_gaugeLevel->SetToolTip(_("Peak of From Radio in Rx, or peak of From Mic in Tx mode. If Red you should reduce your levels"));
levelSizer->Add(m_gaugeLevel, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 10);
leftSizer->Add(levelSizer, 2, wxALIGN_CENTER|wxALL|wxEXPAND, 1);
bSizer1->Add(leftSizer, 0, wxALL|wxEXPAND, 5);
//=====================================================
// Center Section
//=====================================================
wxBoxSizer* centerSizer;
centerSizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* upperSizer;
upperSizer = new wxBoxSizer(wxVERTICAL);
//=====================================================
// Tabbed Notebook control containing display graphs
//=====================================================
//m_auiNbookCtrl = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_BOTTOM|wxAUI_NB_DEFAULT_STYLE);
//long style = wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_CLOSE_ON_ACTIVE_TAB | wxAUI_NB_MIDDLE_CLICK_CLOSE;
long nb_style = wxAUI_NB_BOTTOM | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS;
m_auiNbookCtrl = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, nb_style);
// This line sets the fontsize for the tabs on the notebook control
m_auiNbookCtrl->SetFont(wxFont(8, 70, 90, 90, false, wxEmptyString));
upperSizer->Add(m_auiNbookCtrl, 1, wxALIGN_TOP|wxEXPAND, 1);
centerSizer->Add(upperSizer, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALIGN_TOP|wxEXPAND, 0);
// lower middle used for user ID
wxBoxSizer* lowerSizer;
lowerSizer = new wxBoxSizer(wxHORIZONTAL);
m_BtnCallSignReset = new wxButton(this, wxID_ANY, _("Clear"), wxDefaultPosition, wxDefaultSize, 0);
lowerSizer->Add(m_BtnCallSignReset, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
wxBoxSizer* bSizer15;
bSizer15 = new wxBoxSizer(wxVERTICAL);
m_txtCtrlCallSign = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
m_txtCtrlCallSign->SetToolTip(_("Call Sign of transmitting station will appear here"));
bSizer15->Add(m_txtCtrlCallSign, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5);
lowerSizer->Add(bSizer15, 1, wxEXPAND, 5);
wxStaticBoxSizer* sbSizer_Checksum = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Checksums")), wxHORIZONTAL);
wxStaticText *goodLabel = new wxStaticText(this, wxID_ANY, wxT("Good: "), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
sbSizer_Checksum->Add(goodLabel, 0, 0, 2);
m_txtChecksumGood = new wxStaticText(this, wxID_ANY, wxT("0"), wxDefaultPosition, wxSize(30,-1), wxALIGN_CENTRE);
sbSizer_Checksum->Add(m_txtChecksumGood, 0, 0, 2);
wxStaticText *badLabel = new wxStaticText(this, wxID_ANY, wxT("Bad: "), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
sbSizer_Checksum->Add(badLabel, 0, 0, 1);
m_txtChecksumBad = new wxStaticText(this, wxID_ANY, wxT("0"), wxDefaultPosition, wxSize(30,-1), wxALIGN_CENTRE);
sbSizer_Checksum->Add(m_txtChecksumBad, 0, 0, 1);
lowerSizer->Add(sbSizer_Checksum, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
//=====================================================
// These are the buttons that autosend the userid (?)
//=====================================================
// DR 4 Dec - taken off for screen for Beta release to avoid questions on their use until
// we implement this feature
#ifdef UNIMPLEMENTED
wxBoxSizer* bSizer141;
bSizer141 = new wxBoxSizer(wxHORIZONTAL);
// TxID
//---------
m_togTxID = new wxToggleButton(this, wxID_ANY, _("TxID"), wxDefaultPosition, wxDefaultSize, 0);
m_togTxID->SetToolTip(_("Send Tx ID information"));
bSizer141->Add(m_togTxID, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
// RxID
//---------
m_togRxID = new wxToggleButton(this, wxID_ANY, _("RxID"), wxDefaultPosition, wxDefaultSize, 0);
m_togRxID->SetToolTip(_("Enable reception of ID information"));
bSizer141->Add(m_togRxID, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_LEFT|wxALL|wxFIXED_MINSIZE, 5);
lowerSizer->Add(bSizer141, 0, wxALIGN_RIGHT, 5);
#endif
centerSizer->Add(lowerSizer, 0, wxALIGN_BOTTOM|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 2);
bSizer1->Add(centerSizer, 4, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 1);
//=====================================================
// Right side
//=====================================================
wxBoxSizer* rightSizer;
rightSizer = new wxBoxSizer(wxVERTICAL);
//=====================================================
// Squelch Slider Control
//=====================================================
wxStaticBoxSizer* sbSizer3;
sbSizer3 = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Squelch")), wxVERTICAL);
m_sliderSQ = new wxSlider(this, wxID_ANY, 0, 0, 40, wxDefaultPosition, wxSize(-1,80), wxSL_AUTOTICKS|wxSL_INVERSE|wxSL_VERTICAL);
m_sliderSQ->SetToolTip(_("Set Squelch level in dB."));
sbSizer3->Add(m_sliderSQ, 1, wxALIGN_CENTER_HORIZONTAL, 0);
//------------------------------
// Squelch Level static text box
//------------------------------
m_textSQ = new wxStaticText(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
sbSizer3->Add(m_textSQ, 0, wxALIGN_CENTER_HORIZONTAL, 0);
//------------------------------
// Squelch Toggle Checkbox
//------------------------------
m_ckboxSQ = new wxCheckBox(this, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sbSizer3->Add(m_ckboxSQ, 0, wxALIGN_CENTER_HORIZONTAL, 0);
rightSizer->Add(sbSizer3, 2, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 0);
//rightSizer->Add(sbSizer3_33,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
/* new --- */
//------------------------------
// Mode box
//------------------------------
wxStaticBoxSizer* sbSizer_mode;
sbSizer_mode = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Mode")), wxVERTICAL);
#ifdef DISABLED_FEATURE
m_rb1400old = new wxRadioButton( this, wxID_ANY, wxT("1400 V0.91"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
sbSizer_mode->Add(m_rb1400old, 0, wxALIGN_LEFT|wxALL, 1);
m_rb1400 = new wxRadioButton( this, wxID_ANY, wxT("1400"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_mode->Add(m_rb1400, 0, wxALIGN_LEFT|wxALL, 1);
#endif
m_rb700 = new wxRadioButton( this, wxID_ANY, wxT("700"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
sbSizer_mode->Add(m_rb700, 0, wxALIGN_LEFT|wxALL, 1);
m_rb700b = new wxRadioButton( this, wxID_ANY, wxT("700B"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_mode->Add(m_rb700b, 0, wxALIGN_LEFT|wxALL, 1);
m_rb1600 = new wxRadioButton( this, wxID_ANY, wxT("1600"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_mode->Add(m_rb1600, 0, wxALIGN_LEFT|wxALL, 1);
m_rb1600->SetValue(true);
#ifdef DISABLED_FEATURE
m_rb1600Wide = new wxRadioButton( this, wxID_ANY, wxT("1600 Wide"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_mode->Add(m_rb1600Wide, 0, wxALIGN_LEFT|wxALL, 1);
m_rb2000 = new wxRadioButton( this, wxID_ANY, wxT("2000"), wxDefaultPosition, wxDefaultSize, 0);
sbSizer_mode->Add(m_rb2000, 0, wxALIGN_LEFT|wxALL, 1);
#endif
rightSizer->Add(sbSizer_mode,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
#ifdef MOVED_TO_OPTIONS_DIALOG
/* new --- */
//------------------------------
// Test Frames box
//------------------------------
wxStaticBoxSizer* sbSizer_testFrames;
sbSizer_testFrames = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Test Frames")), wxVERTICAL);
m_ckboxTestFrame = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
sbSizer_testFrames->Add(m_ckboxTestFrame, 0, wxALIGN_LEFT, 0);
rightSizer->Add(sbSizer_testFrames,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3);
#endif
//=====================================================
// Control Toggles box
//=====================================================
wxStaticBoxSizer* sbSizer5;
sbSizer5 = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Control")), wxVERTICAL);
wxBoxSizer* bSizer1511;
bSizer1511 = new wxBoxSizer(wxVERTICAL);
//-------------------------------
// Stop/Stop signal processing (rx and tx)
//-------------------------------
m_togBtnOnOff = new wxToggleButton(this, wxID_ANY, _("Start"), wxDefaultPosition, wxDefaultSize, 0);
m_togBtnOnOff->SetToolTip(_("Begin/End receiving data."));
bSizer1511->Add(m_togBtnOnOff, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
sbSizer5->Add(bSizer1511, 0, wxEXPAND, 1);
#ifdef UNIMPLEMENTED
//------------------------------
// Toggle Loopback button for RX
//------------------------------
wxBoxSizer* bSizer15113;
bSizer15113 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* bSizer15111;
bSizer15111 = new wxBoxSizer(wxVERTICAL);
wxSize wxSz = wxSize(44, 30);
m_togBtnLoopRx = new wxToggleButton(this, wxID_ANY, _("Loop\nRX"), wxDefaultPosition, wxSz, 0);
m_togBtnLoopRx->SetFont(wxFont(6, 70, 90, 90, false, wxEmptyString));
m_togBtnLoopRx->SetToolTip(_("Loopback Receive audio data."));
bSizer15111->Add(m_togBtnLoopRx, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 0);
//sbSizer5->Add(bSizer15111, 0, wxEXPAND, 1);
bSizer15113->Add(bSizer15111, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 0);
//------------------------------
// Toggle Loopback button for Tx
//------------------------------
wxBoxSizer* bSizer15112;
bSizer15112 = new wxBoxSizer(wxVERTICAL);
m_togBtnLoopTx = new wxToggleButton(this, wxID_ANY, _("Loop\nTX"), wxDefaultPosition, wxSz, 0);
m_togBtnLoopTx->SetFont(wxFont(6, 70, 90, 90, false, wxEmptyString));
m_togBtnLoopTx->SetToolTip(_("Loopback Transmit audio data."));
bSizer15112->Add(m_togBtnLoopTx, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 0);
bSizer15113->Add(bSizer15112, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 0);
sbSizer5->Add(bSizer15113, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
#endif
//------------------------------
// Split Frequency Mode Toggle
//------------------------------
wxBoxSizer* bSizer151;
bSizer151 = new wxBoxSizer(wxVERTICAL);
m_togBtnSplit = new wxToggleButton(this, wxID_ANY, _("Split"), wxDefaultPosition, wxDefaultSize, 0);
m_togBtnSplit->SetToolTip(_("Toggle split frequency mode."));
bSizer151->Add(m_togBtnSplit, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
sbSizer5->Add(bSizer151, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 1);
wxBoxSizer* bSizer13;
bSizer13 = new wxBoxSizer(wxVERTICAL);
//------------------------------
// Analog Passthrough Toggle
//------------------------------
m_togBtnAnalog = new wxToggleButton(this, wxID_ANY, _("Analog"), wxDefaultPosition, wxDefaultSize, 0);
m_togBtnAnalog->SetToolTip(_("Toggle analog/digital operation."));
bSizer13->Add(m_togBtnAnalog, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
sbSizer5->Add(bSizer13, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
// not implemented on fdmdv2
#ifdef ALC
//------------------------------
// Toggle for ALC
//------------------------------
wxBoxSizer* bSizer14;
bSizer14 = new wxBoxSizer(wxVERTICAL);
m_togBtnALC = new wxToggleButton(this, wxID_ANY, _("ALC"), wxDefaultPosition, wxDefaultSize, 0);
m_togBtnALC->SetToolTip(_("Toggle automatic level control mode."));
bSizer14->Add(m_togBtnALC, 0, wxALL, 1);
sbSizer5->Add(bSizer14, 0, wxALIGN_CENTER|wxALIGN_CENTER_HORIZONTAL|wxALL, 1);
#endif
//------------------------------
// Toggle Transmit/Receive relays
//------------------------------
wxBoxSizer* bSizer11;
bSizer11 = new wxBoxSizer(wxVERTICAL);
m_btnTogPTT = new wxToggleButton(this, wxID_ANY, _("PTT"), wxDefaultPosition, wxDefaultSize, 0);
m_btnTogPTT->SetToolTip(_("Push to Talk - Switch between Receive and Transmit - you can also use the space bar "));
bSizer11->Add(m_btnTogPTT, 1, wxALIGN_CENTER|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 1);
sbSizer5->Add(bSizer11, 2, wxEXPAND, 1);
rightSizer->Add(sbSizer5, 2, wxALIGN_CENTER|wxALL|wxEXPAND, 3);
bSizer1->Add(rightSizer, 0, wxALL|wxEXPAND, 3);
this->SetSizer(bSizer1);
this->Layout();
m_statusBar1 = this->CreateStatusBar(3, wxST_SIZEGRIP, wxID_ANY);
//=====================================================
// End of layout
//=====================================================
//-------------------
// Connect Events
//-------------------
this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(TopFrame::topFrame_OnClose));
this->Connect(wxEVT_PAINT, wxPaintEventHandler(TopFrame::topFrame_OnPaint));
this->Connect(wxEVT_SIZE, wxSizeEventHandler(TopFrame::topFrame_OnSize));
this->Connect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::topFrame_OnUpdateUI));
this->Connect(m_menuItemExit->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnExit));
this->Connect(m_menuItemOnTop->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnTop));
this->Connect(m_menuItemAudio->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsAudio));
this->Connect(m_menuItemAudio->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsAudioUI));
this->Connect(m_menuItemFilter->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsFilter));
this->Connect(m_menuItemFilter->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsFilterUI));
this->Connect(m_menuItemRigCtrlCfg->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsComCfg));
this->Connect(m_menuItemRigCtrlCfg->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsComCfgUI));
this->Connect(m_menuItemOptions->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsOptions));
this->Connect(m_menuItemOptions->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsOptionsUI));
this->Connect(m_menuItemPlayFileToMicIn->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnPlayFileToMicIn));
this->Connect(m_menuItemRecFileFromRadio->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnRecFileFromRadio));
this->Connect(m_menuItemPlayFileFromRadio->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnPlayFileFromRadio));
this->Connect(m_menuItemHelpUpdates->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpCheckUpdates));
this->Connect(m_menuItemHelpUpdates->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnHelpCheckUpdatesUI));
this->Connect(m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpAbout));
//m_togRxID->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnRxID), NULL, this);
//m_togTxID->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnTxID), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_PAGEUP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnSliderScrollBottom), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(TopFrame::OnCmdSliderScrollChanged), NULL, this);
m_sliderSQ->Connect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnSliderScrollTop), NULL, this);
m_ckboxSQ->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(TopFrame::OnCheckSQClick), NULL, this);
m_ckboxSNR->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(TopFrame::OnCheckSNRClick), NULL, this);
m_togBtnOnOff->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnOnOff), NULL, this);
m_togBtnSplit->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnSplitClick), NULL, this);
m_togBtnAnalog->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnAnalogClick), NULL, this);
#ifdef ALC
m_togBtnALC->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnALCClick), NULL, this);
#endif
m_btnTogPTT->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnPTT), NULL, this);
m_BtnCallSignReset->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCallSignReset), NULL, this);
m_BtnBerReset->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnBerReset), NULL, this);
}
TopFrame::~TopFrame()
{
//-------------------
// Disconnect Events
//-------------------
this->Disconnect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(TopFrame::topFrame_OnClose));
this->Disconnect(wxEVT_PAINT, wxPaintEventHandler(TopFrame::topFrame_OnPaint));
this->Disconnect(wxEVT_SIZE, wxSizeEventHandler(TopFrame::topFrame_OnSize));
this->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::topFrame_OnUpdateUI));
this->Disconnect(ID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnExit));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsAudio));
this->Disconnect(wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsAudioUI));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsFilter));
this->Disconnect(wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsFilterUI));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsComCfg));
this->Disconnect(wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsComCfgUI));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnToolsOptions));
this->Disconnect(wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnToolsOptionsUI));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnPlayFileToMicIn));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnRecFileFromRadio));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnPlayFileFromRadio));
this->Disconnect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpCheckUpdates));
this->Disconnect(wxID_ANY, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnHelpCheckUpdatesUI));
this->Disconnect(ID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpAbout));
//m_togRxID->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnRxID), NULL, this);
//m_togTxID->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnTxID), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_PAGEUP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnSliderScrollBottom), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_CHANGED, wxScrollEventHandler(TopFrame::OnCmdSliderScrollChanged), NULL, this);
m_sliderSQ->Disconnect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnSliderScrollTop), NULL, this);
m_ckboxSQ->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(TopFrame::OnCheckSQClick), NULL, this);
m_togBtnOnOff->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnOnOff), NULL, this);
m_togBtnSplit->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnSplitClick), NULL, this);
m_togBtnAnalog->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnAnalogClick), NULL, this);
#ifdef ALC
m_togBtnALC->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnALCClick), NULL, this);
#endif
m_btnTogPTT->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnPTT), NULL, this);
}

184
src/topFrame.h 100644
View File

@ -0,0 +1,184 @@
//==========================================================================
// Name: topFrame.h
//
// Purpose: Implements simple wxWidgets application with GUI.
// Created: Apr. 9, 2012
// Authors: David Rowe, David Witten
//
// License:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version 2.1,
// as published by the Free Software Foundation. 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 Lesser General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//
//==========================================================================
#ifndef __TOPFRAME_H__
#define __TOPFRAME_H__
#include "version.h"
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/menu.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/gauge.h>
#include <wx/textctrl.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/aui/auibook.h>
#include <wx/tglbtn.h>
#include <wx/slider.h>
#include <wx/checkbox.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
#include <wx/statbmp.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/dialog.h>
#include <wx/radiobut.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/listbox.h>
#include <wx/notebook.h>
#include <wx/listctrl.h>
///////////////////////////////////////////////////////////////////////////
#define ID_OPEN 1000
#define ID_SAVE 1001
#define ID_CLOSE 1002
#define ID_EXIT 1003
#define ID_COPY 1004
#define ID_CUT 1005
#define ID_PASTE 1006
#define ID_OPTIONS 1007
#define ID_ABOUT 1008
///////////////////////////////////////////////////////////////////////////////
/// Class TopFrame
///////////////////////////////////////////////////////////////////////////////
class TopFrame : public wxFrame
{
private:
protected:
wxMenuBar* m_menubarMain;
wxMenu* file;
wxMenu* edit;
wxMenu* tools;
wxMenu* help;
wxGauge* m_gaugeSNR;
wxStaticText* m_textSNR;
wxCheckBox* m_ckboxSNR;
wxGauge* m_gaugeLevel;
wxStaticText* m_textLevel;
wxButton* m_BtnCallSignReset;
wxTextCtrl* m_txtCtrlCallSign;
wxStaticText* m_txtChecksumGood;
wxStaticText* m_txtChecksumBad;
wxSlider* m_sliderSQ;
wxCheckBox* m_ckboxSQ;
wxStaticText* m_textSQ;
wxStatusBar* m_statusBar1;
wxButton* m_BtnBerReset;
wxStaticText *m_textBits;
wxStaticText *m_textErrors;
wxStaticText *m_textBER;
wxRadioButton *m_rbSync;
wxRadioButton *m_rb1400old;
wxRadioButton *m_rb1400;
wxRadioButton *m_rb700;
wxRadioButton *m_rb700b;
wxRadioButton *m_rb1600;
wxRadioButton *m_rb2000;
wxRadioButton *m_rb1600Wide;
// Virtual event handlers, overide them in your derived class
virtual void topFrame_OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void topFrame_OnPaint( wxPaintEvent& event ) { event.Skip(); }
virtual void topFrame_OnSize( wxSizeEvent& event ) { event.Skip(); }
virtual void topFrame_OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnExit( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTop( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsAudio( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsAudioUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnToolsFilter( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsFilterUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnToolsOptions( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsUDP( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsOptionsUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnToolsComCfg( wxCommandEvent& event ) { event.Skip(); }
virtual void OnToolsComCfgUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnPlayFileToMicIn( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRecFileFromRadio( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPlayFileFromRadio( wxCommandEvent& event ) { event.Skip(); }
virtual void OnHelpCheckUpdates( wxCommandEvent& event ) { event.Skip(); }
virtual void OnHelpCheckUpdatesUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnHelpAbout( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnRxID( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnTxID( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCmdSliderScroll( wxScrollEvent& event ) { event.Skip(); }
virtual void OnSliderScrollBottom( wxScrollEvent& event ) { event.Skip(); }
virtual void OnCmdSliderScrollChanged( wxScrollEvent& event ) { event.Skip(); }
virtual void OnSliderScrollTop( wxScrollEvent& event ) { event.Skip(); }
virtual void OnCheckSQClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCheckSNRClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnLoopRx( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnLoopTx( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnOnOff( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnSplitClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnAnalogClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnALCClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnPTT( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTogBtnSplitClickUI(wxUpdateUIEvent& event) { event.Skip(); }
virtual void OnTogBtnAnalogClickUI(wxUpdateUIEvent& event) { event.Skip(); }
virtual void OnTogBtnALCClickUI(wxUpdateUIEvent& event) { event.Skip(); }
virtual void OnTogBtnRxIDUI(wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnTogBtnTxIDUI(wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnTogBtnPTT_UI(wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnTogBtnOnOffUI(wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnCallSignReset( wxCommandEvent& event ) { event.Skip(); }
virtual void OnBerReset( wxCommandEvent& event ) { event.Skip(); }
public:
wxToggleButton* m_togRxID;
wxToggleButton* m_togTxID;
wxToggleButton* m_togBtnOnOff;
wxToggleButton* m_togBtnSplit;
wxToggleButton* m_togBtnAnalog;
wxToggleButton* m_togBtnALC;
wxToggleButton* m_btnTogPTT;
wxToggleButton* m_togBtnLoopRx;
wxToggleButton* m_togBtnLoopTx;
wxAuiNotebook* m_auiNbookCtrl;
TopFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("FreeDV ") + _(FREEDV_VERSION), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(561,300 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~TopFrame();
};
#endif //__TOPFRAME_H__