FS-10510: [Build-System] Add mod_codec2, move libcodec2 from tree to download on windows.
This commit is contained in:
parent
c237bd60f9
commit
c1d964a0a5
|
@ -252,3 +252,4 @@ libs/lua-*/
|
|||
libs/g722_1-*/
|
||||
libs/ilbc-*/
|
||||
libs/broadvoice-*/
|
||||
libs/libcodec2-*/
|
||||
|
|
|
@ -659,6 +659,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download iLBC", "libs\win32
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download broadvoice", "libs\win32\Download broadvoice.2015.vcxproj", "{46502007-0D94-47AC-A640-C2B5EEA98333}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcodec2", "libs\win32\libcodec2\libcodec2.2015.vcxproj", "{19E934D6-1484-41C8-9305-78DC42FD61F2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_codec2", "src\mod\codecs\mod_codec2\mod_codec2.vcxproj", "{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download libcodec2", "libs\win32\Download libcodec2.2015.vcxproj", "{9CFA562C-C611-48A7-90A2-BB031B47FE6D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
All|Win32 = All|Win32
|
||||
|
@ -2977,6 +2983,42 @@ Global
|
|||
{46502007-0D94-47AC-A640-C2B5EEA98333}.Release|Win32.Build.0 = Release|Win32
|
||||
{46502007-0D94-47AC-A640-C2B5EEA98333}.Release|x64.ActiveCfg = Release|Win32
|
||||
{46502007-0D94-47AC-A640-C2B5EEA98333}.Release|x64.Build.0 = Release|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.All|Win32.ActiveCfg = Release|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.All|Win32.Build.0 = Release|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.All|x64.ActiveCfg = Release|x64
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.All|x64.Build.0 = Release|x64
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Debug|x64.Build.0 = Debug|x64
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Release|Win32.Build.0 = Release|Win32
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Release|x64.ActiveCfg = Release|x64
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2}.Release|x64.Build.0 = Release|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.All|Win32.ActiveCfg = Release|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.All|Win32.Build.0 = Release|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.All|x64.ActiveCfg = Release|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.All|x64.Build.0 = Release|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Debug|x64.Build.0 = Debug|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Release|Win32.Build.0 = Release|Win32
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Release|x64.ActiveCfg = Release|x64
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17}.Release|x64.Build.0 = Release|x64
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.All|Win32.ActiveCfg = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.All|Win32.Build.0 = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.All|x64.ActiveCfg = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.All|x64.Build.0 = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Debug|x64.Build.0 = Debug|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Release|Win32.Build.0 = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Release|x64.ActiveCfg = Release|Win32
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D}.Release|x64.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -3213,5 +3255,8 @@ Global
|
|||
{36603FE1-253F-4C2C-AAB6-12927A626135} = {C120A020-773F-4EA3-923F-B67AF28B750D}
|
||||
{53AADA60-DF12-46FF-BF94-566BBF849336} = {C120A020-773F-4EA3-923F-B67AF28B750D}
|
||||
{46502007-0D94-47AC-A640-C2B5EEA98333} = {C120A020-773F-4EA3-923F-B67AF28B750D}
|
||||
{19E934D6-1484-41C8-9305-78DC42FD61F2} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
|
||||
{CB4E68A1-8D19-4B5E-87B9-97A895E1BA17} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
|
||||
{9CFA562C-C611-48A7-90A2-BB031B47FE6D} = {C120A020-773F-4EA3-923F-B67AF28B750D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
src/codebookvq.c
|
|
@ -1,502 +0,0 @@
|
|||
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!
|
|
@ -1,94 +0,0 @@
|
|||
AM_CFLAGS = -Isrc -fPIC -Wall -O3 -lm
|
||||
AUTOMAKE_OPTIONS = gnu
|
||||
NAME = codec2
|
||||
AM_CPPFLAGS = $(AM_CFLAGS)
|
||||
|
||||
EXTRA_DIST = octave/glottal.m \
|
||||
octave/lsp_pdf.m \
|
||||
octave/phase.m \
|
||||
octave/pl2.m \
|
||||
octave/plinterp.m \
|
||||
octave/plnlp.m \
|
||||
octave/plpitch.m \
|
||||
octave/postfilter.m \
|
||||
octave/load_raw.m \
|
||||
octave/phase2.m \
|
||||
octave/pitch_test.m \
|
||||
octave/plamp.m \
|
||||
octave/pl.m \
|
||||
octave/plphase.m \
|
||||
octave/png.m \
|
||||
octave/pulse.m \
|
||||
raw/b0067.raw \
|
||||
raw/forig_speex_8k.raw \
|
||||
raw/hts1.raw \
|
||||
raw/hts2.raw \
|
||||
raw/mmt1.raw \
|
||||
raw/morig_speex_8k.raw \
|
||||
raw/f2400.raw \
|
||||
raw/hts1a_g729a.raw \
|
||||
raw/hts2a_g729a.raw \
|
||||
raw/hts.raw \
|
||||
raw/mmt1_speex_8k.raw \
|
||||
raw/forig_g729a.raw \
|
||||
raw/hts1a_gsm13k.raw \
|
||||
raw/hts2a_gsm13k.raw \
|
||||
raw/m2400.raw \
|
||||
raw/morig_g729a.raw \
|
||||
raw/forig_gsm13k.raw \
|
||||
raw/hts1a.raw \
|
||||
raw/hts2a.raw \
|
||||
raw/mmt1_g729a.raw \
|
||||
raw/morig_gsm13k.raw \
|
||||
raw/forig.raw \
|
||||
raw/hts1a_speex_8k.raw \
|
||||
raw/hts2a_speex_8k.raw \
|
||||
raw/mmt1_gsm13k.raw \
|
||||
raw/morig.raw \
|
||||
script/menu.sh \
|
||||
script/playraw.sh \
|
||||
script/raw2wav.sh \
|
||||
script/wav2raw.sh \
|
||||
wav/f2400.wav \
|
||||
wav/hts1a_c2_v0.1.wav \
|
||||
wav/hts1a.wav \
|
||||
wav/hts2a_speex_8k.wav \
|
||||
wav/mmt1_speex_8k.wav \
|
||||
wav/morig.wav \
|
||||
wav/forig_speex_8k.wav \
|
||||
wav/hts1a_g729a.wav \
|
||||
wav/hts2a_c2_v0.1.wav \
|
||||
wav/hts2a.wav \
|
||||
wav/mmt1.wav \
|
||||
wav/forig.wav \
|
||||
wav/hts1a_speex_8k.wav \
|
||||
wav/hts2a_g729a.wav \
|
||||
wav/m2400.wav \
|
||||
wav/morig_speex_8k.wav \
|
||||
src/globals.c \
|
||||
unittest/lsp2.txt \
|
||||
unittest/lsp7.txt \
|
||||
unittest/lspd78.txt \
|
||||
unittest/lsp3.txt \
|
||||
unittest/lsp8.txt \
|
||||
unittest/lspd910.txt \
|
||||
unittest/lsp4.txt \
|
||||
unittest/lsp9.txt \
|
||||
unittest/lsp10.txt \
|
||||
unittest/lsp5.txt \
|
||||
unittest/lspd123.txt \
|
||||
unittest/lsp1.txt \
|
||||
unittest/lsp6.txt \
|
||||
unittest/lspd456.txt \
|
||||
src/codebook/lsp1.txt \
|
||||
src/codebook/lsp2.txt \
|
||||
src/codebook/lsp3.txt \
|
||||
src/codebook/lsp4.txt \
|
||||
src/codebook/lsp5.txt \
|
||||
src/codebook/lsp6.txt \
|
||||
src/codebook/lsp7.txt \
|
||||
src/codebook/lsp8.txt \
|
||||
src/codebook/lsp9.txt \
|
||||
src/codebook/lsp10.txt
|
||||
|
||||
SUBDIRS = src unittest
|
|
@ -1,84 +0,0 @@
|
|||
Codec 2 README
|
||||
--------------
|
||||
|
||||
Codec 2 is an open source (LGPL licensed) speech codec for 2400 bit/s
|
||||
and below. For more information please see:
|
||||
|
||||
http://rowetel.com/codec2.html
|
||||
|
||||
Also included is a FDMDV modem, see README_fdmdv.txt
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
1/ Listen to Codec 2:
|
||||
|
||||
$ ./configure && make
|
||||
$ cd src
|
||||
$ ./c2demo ../raw/hts1a.raw hts1a_c2.raw
|
||||
$ ../script/menu.sh ../raw/hts1a.raw hts1a_c2.raw
|
||||
|
||||
NOTE: For playback testing, menu.sh requires either the 'play',
|
||||
'aplay' or 'ossplay' programs to be installed (see
|
||||
http://sox.sourceforge.net/, http://www.alsa-project.org/, or
|
||||
http://www.opensound.com/ respectively).
|
||||
|
||||
2/ Compress and Decompress a file:
|
||||
|
||||
$ ./c2enc 2400 ../raw/hts1a.raw hts1a_c2.bit
|
||||
$ ./c2dec 2400 hts1a_c2.bit hts1a_c2.raw
|
||||
|
||||
3/ Same thing with pipes:
|
||||
|
||||
$ ./c2enc 1400 ../raw/hts1a.raw - | ./c2dec 1400 - - | play -t raw -r 8000 -s -2 -
|
||||
|
||||
Programs
|
||||
--------
|
||||
|
||||
1/ c2demo encodes a file of speech samples, then decodes them and
|
||||
saves the result.
|
||||
|
||||
2/ c2enc encodes a file of speech samples to a compressed file of
|
||||
encoded bits.
|
||||
|
||||
3/ c2dec decodes a compressed file of bits to a file of speech
|
||||
samples.
|
||||
|
||||
4/ c2sim is a simulation/development version of Codec 2. It allows
|
||||
selective use of the various Codec 2 algorithms. For example
|
||||
switching phase modelling or LSP quantisation on and off.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
1/ For dump file support:
|
||||
|
||||
$ cd codec2
|
||||
$ CFLAGS=-DDUMP ./configure
|
||||
$ make clean && make
|
||||
|
||||
2/ To use gdb:
|
||||
|
||||
$ libtool --mode=execute gdb c2sim
|
||||
|
||||
Directories
|
||||
-----------
|
||||
|
||||
fltk - FLTK GUI programs(s)
|
||||
octave - Octave scripts used for visualising internal signals
|
||||
during development
|
||||
portaudio - Portaudio test programs
|
||||
script - shell scripts for playing and converting raw files
|
||||
src - C source code
|
||||
raw - speech files in raw format (16 bits signed linear 8 kHz)
|
||||
unittest - unit test source code
|
||||
voicing - hand-estimated voicing files, used for development
|
||||
wav - speech files in wave file format
|
||||
win32 - Support for building Windows DLL version of Codec 2 and FDMDV libraries
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
[ ] Get win32/Makefile integrated into Automake system, such that if
|
||||
i586-mingw32msvc exists the Win32 code gets automatically built.
|
||||
[ ] Same for fltk & portaudio, build these conditionally if libs exist
|
|
@ -1,199 +0,0 @@
|
|||
|
||||
README_fdmdv.txt
|
||||
David Rowe
|
||||
Created March 2012
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A 1400 bit/s Frequency Division Multiplexed Digital Voice (FDMDV) modem
|
||||
based on [1]. Used for digital audio over HF SSB.
|
||||
|
||||
The FDMDV modem was first implemented in GNU Octave, then ported to C.
|
||||
Algorithm development is generally easier in Octave, but for real time
|
||||
work we need the C version. Automated units tests ensure the
|
||||
operation of the Octave and C versions are identical.
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
$ cd codec2-dev
|
||||
$ ./configure && make
|
||||
$ cd src
|
||||
|
||||
1. Generate some test bits and modulate them:
|
||||
|
||||
$ ./fdmdv_get_test_bits test.c2 1400
|
||||
$ ./fdmdv_mod test.c2 test.raw
|
||||
$ play -r 8000 -s -2 test.raw
|
||||
|
||||
2. Two seconds of test frame data modulated and sent out of sound device:
|
||||
|
||||
$ ./fdmdv_get_test_bits - 2800 | ./fdmdv_mod - - | play -t raw -r 8000 -s -2 -
|
||||
|
||||
3. Send 14000 modulated bits (10 seconds) to the demod and count errors:
|
||||
|
||||
$ ./fdmdv_get_test_bits - 14000 | ./fdmdv_mod - - | ./fdmdv_demod - - demod_dump.txt | ./fdmdv_put_test_bits -
|
||||
|
||||
Use Octave to look at plots of 1 second (1400 bits) of modem operation:
|
||||
|
||||
$ cd ../octave
|
||||
$ octave
|
||||
octave:1> fdmdv_demod_c("../src/demod_dump.txt",1400)
|
||||
|
||||
4. Run Octave simulation of entire modem and AWGN channel:
|
||||
|
||||
$ cd ../octave
|
||||
$ octave
|
||||
octave:1> fdmdv_ut
|
||||
|
||||
5. NOTE: If you would like to play modem samples over the air please
|
||||
convert the 8 kHz samples to 48 kHz. Many PC sound cards have
|
||||
wildly inaccurate sample clock rates when set to 8 kHz, but seem to
|
||||
perform OK when set for 48 kHz. If playing and recording files you
|
||||
can use the sox utility:
|
||||
|
||||
$ sox -r 8000 -s -2 modem_sample_8kHz.raw -r 48000 modem_sample_48kHz.wav
|
||||
|
||||
For real time applications, the fdmdv.[ch] library includes functions to
|
||||
convert between 48 and 8 kHz sample rates.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
[1] http://n1su.com/fdmdv/FDMDV_Docs_Rel_1_4b.pdf
|
||||
[2] http://n1su.com/fdmdv/
|
||||
[3] http://www.rowetel.com/blog/?p=2433 "Testing a FDMDV Modem"
|
||||
[4] http://www.rowetel.com/blog/?p=2458 "FDMDV Modem Page" on David's web site
|
||||
|
||||
C Code
|
||||
------
|
||||
|
||||
src/fdmdv_mod.c - C version of modulator that takes a file of bits and
|
||||
converts it to a raw file of modulated samples.
|
||||
|
||||
src/fdmdv_demod.c - C version of demodulator that takes a raw file of
|
||||
modulated samples and outputs a file of bits.
|
||||
Optionally dumps demod states to a text file which
|
||||
can be plotted using the Octave script
|
||||
fdmdv_demod_c.m
|
||||
|
||||
src/fdmdv.h - Header file that exposes FDMDV C API functions. Include
|
||||
this file in your application program.
|
||||
|
||||
src/fdmdv.c - C functions that implement the FDMDV modem.
|
||||
|
||||
src/fdmdv-internal.h - internal states and constants for FDMDV modem,
|
||||
shouldn't be exposed to application program.
|
||||
|
||||
|
||||
unittest/tfdmdv.c - Used to conjunction with unittest/tfdmdv.m to
|
||||
automatically test C FDMDV functions against
|
||||
Octave versions.
|
||||
|
||||
Octave Scripts
|
||||
--------------
|
||||
|
||||
(Note these require some Octave packages to be installed, see
|
||||
octave/README.txt).
|
||||
|
||||
fdmdv.m - Functions and variables that implement the Octave version of
|
||||
the FDMDV modem.
|
||||
|
||||
fdmdv_ut.m - Unit test for fdmdv Octave code, useful while
|
||||
developing algorithm. Includes tx/rx plus basic channel
|
||||
simulation.
|
||||
|
||||
Typical run:
|
||||
|
||||
octave:6> fdmdv_ut
|
||||
Eb/No (meas): 7.30 (8.29) dB
|
||||
bits........: 2464
|
||||
errors......: 20
|
||||
BER.........: 0.0081
|
||||
PAPR........: 13.54 dB
|
||||
SNR.........: 4.0 dB
|
||||
|
||||
It also outputs lots of nice plots that show the
|
||||
operation of the modem.
|
||||
|
||||
For a 1400 bit/s DQPSK modem we expect about 1% BER for
|
||||
Eb/No = 7.3dB, which corresponds to SNR = 4dB (3kHz
|
||||
noise BW). The extra dB of measured power is due to the
|
||||
DBPSK pilot. Currently the noise generation code
|
||||
doesn't take the pilot power into account, so in this
|
||||
example the real SNR is actually 5dB.
|
||||
|
||||
fdmdv_mod.m - Octave version of modulator that outputs a raw file.
|
||||
The modulator is driven by a test frame of bits. This
|
||||
can then be played over a real channel or through a
|
||||
channel simulator like PathSim. The sample rate can be
|
||||
changed using "sox" to simulate differences in tx/rx
|
||||
sample clocks.
|
||||
|
||||
To generate 10 seconds of modulated signal:
|
||||
|
||||
octave:8> fdmdv_mod("test.raw",1400*10);
|
||||
|
||||
fdmdv_demod.m - Demodulator program that takes a raw file as input,
|
||||
and works out the bit error rate using the known test
|
||||
frame. Can be used to test the demod performs with
|
||||
off-air signals, or signals that have been passed
|
||||
through a channel simulator.
|
||||
|
||||
To demodulate 2 seconds of the test.raw file generated
|
||||
above:
|
||||
|
||||
octave:9> fdmdv_demod("test.raw",1400*2);
|
||||
2464 bits 0 errors BER: 0.0000
|
||||
|
||||
It also produces several plots showing the internal
|
||||
states of the demod. Useful for debugging and
|
||||
observing what happens with various channels.
|
||||
|
||||
fdmdv_demod_c.m - Takes an output text file from the C demod
|
||||
fdmdv_demod.c and produces plots and measures BER.
|
||||
Useful for evaluating fdmdv_demod.c performance.
|
||||
The plots produced are identical to the Octave
|
||||
version fdmdv_demod.m, allowing direct comparison of
|
||||
the C and Octave versions.
|
||||
|
||||
tfdmdv.m - Automatic tests that compare the Octave and C versions of
|
||||
the FDMDV modem functions. First run unittest/tfdmdv, this
|
||||
will generate a text file with test vectors from the C
|
||||
version. Then run the Octave script tfdmdv and it will
|
||||
generate Octave versions of the test vectors and compare
|
||||
each vector with the C equivalent. Its plots the vectors
|
||||
and and errors (green). Its also produces an automatic
|
||||
check list based on test results. If the Octave or C modem
|
||||
code is changed, this script should be used to ensure the
|
||||
C and Octave versions remain identical.
|
||||
|
||||
Modelling sample clock errors using sox
|
||||
---------------------------------------
|
||||
|
||||
This introduces a simulated 1000ppm error:
|
||||
|
||||
sox -r 8000 -s -2 mod_dqpsk.raw -s -2 mod_dqpsk_8008hz.raw rate -h 8008
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
[ ] implement ppm measurements in fdmdv_get_demod_stats()
|
||||
[ ] try interfering sine wave
|
||||
+ maybe swept
|
||||
+ does modem fall over?
|
||||
[ ] try non-flat channel, e.g. 3dB difference between hi and low tones
|
||||
+ make sure all estimators keep working
|
||||
[ ] test rx level sensitivity, i.e. 0 to 20dB attenuation
|
||||
[ ] make fine freq indep of amplitude
|
||||
+ use angle rather than imag coord
|
||||
[ ] document use of fdmdv_ut and fdmdv_demod + PathSim
|
||||
[ ] more positive form of sync reqd for DV frames?
|
||||
+ like using coarse_fine==1 to decode valid DV frame bit?
|
||||
+ when should we start decoding?
|
||||
[ ] more robust track/acquite state machine?
|
||||
+ e.g. hang on thru the fades?
|
||||
[ ] PAPR idea
|
||||
+ automatically tweak phases to reduce PAPR, e.g. slow variations in freq...
|
||||
[ ] why is pilot noise_est twice as big as other carriers
|
|
@ -1,109 +0,0 @@
|
|||
README for codec2/asterisk
|
||||
Asterisk Codec 2 support
|
||||
|
||||
Test Configuration
|
||||
------------------
|
||||
|
||||
Codec 2 is used to trunk calls between two Asterisk boxes:
|
||||
|
||||
A - SIP phone - Asterisk A - Codec2 - Asterisk B - SIP Phone - B
|
||||
|
||||
The two SIP phones are configured for mulaw.
|
||||
|
||||
Building
|
||||
---------
|
||||
|
||||
Asterisk must be patched so that the core understand Codec 2 frames.
|
||||
|
||||
1/ First install Codec 2:
|
||||
|
||||
david@cool:~$ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/codec2-dev codec2-dev
|
||||
david@cool:~/codec2-dev$ cd codec2-dev
|
||||
david@cool:~/codec2-dev$ ./configure && make && sudo make install
|
||||
david@bear:~/codec2-dev$ sudo ldconfig -v
|
||||
david@cool:~/codec2-dev$ cd ~
|
||||
|
||||
2/ Then build Asterisk with Codec 2 support:
|
||||
|
||||
david@cool:~$ tar xvzf asterisk-1.8.9.0.tar.gz
|
||||
david@cool:~/asterisk-1.8.9.0$ patch -p4 < ~/codec2-dev/asterisk/asterisk-codec2.patch
|
||||
david@cool:~/asterisk-1.8.9.0$ cp ~/codec2-dev/asterisk/codec_codec2.c .
|
||||
david@cool:~/asterisk-1.8.9.0$ cp ~/codec2-dev/asterisk/ex_codec2.h ./codecs
|
||||
david@cool:~/asterisk-1.8.9.0$ ./configure && make ASTLDFLAGS=-lcodec2
|
||||
david@cool:~/asterisk-1.8.9.0$ sudo make install
|
||||
david@cool:~/asterisk-1.8.9.0$ sudo make samples
|
||||
|
||||
3/ Add this to the end of sip.conf on Asterisk A:
|
||||
|
||||
[6013]
|
||||
type=friend
|
||||
context=default
|
||||
host=dynamic
|
||||
user=6013
|
||||
secret=6013
|
||||
canreinvite=no
|
||||
callerid=6013
|
||||
disallow=all
|
||||
allow=ulaw
|
||||
|
||||
[potato]
|
||||
type=peer
|
||||
username=potato
|
||||
fromuser=potato
|
||||
secret=password
|
||||
context=default
|
||||
disallow=all
|
||||
dtmfmode=rfc2833
|
||||
callerid=server
|
||||
canreinvite=no
|
||||
host=cool
|
||||
allow=codec2
|
||||
|
||||
3/ Add this to the end of sip.conf on Asterisk B:
|
||||
|
||||
[6014]
|
||||
type=friend
|
||||
context=default
|
||||
host=dynamic
|
||||
user=6014
|
||||
secret=6014
|
||||
canreinvite=no
|
||||
callerid=6014
|
||||
disallow=all
|
||||
allow=ulaw
|
||||
|
||||
[potato]
|
||||
type=peer
|
||||
username=potato
|
||||
fromuser=potato
|
||||
secret=password
|
||||
context=default
|
||||
disallow=all
|
||||
dtmfmode=rfc2833
|
||||
callerid=server
|
||||
canreinvite=no
|
||||
host=bear
|
||||
allow=codec2
|
||||
|
||||
4/ Here is the [default] section of extensions.conf on Asterisk B:
|
||||
|
||||
[default]
|
||||
|
||||
exten => 6013,1,Dial(SIP/potato/6013)
|
||||
;
|
||||
; By default we include the demo. In a production system, you
|
||||
; probably don't want to have the demo there.
|
||||
;
|
||||
;include => demo
|
||||
|
||||
5/ After booting see if the codec2_codec2.so module is loaded with "core show translate"
|
||||
|
||||
6/ To make a test call dial 6013 on the SIP phone connected to Asterisk B
|
||||
|
||||
7/ If codec_codec2.so won't load and you see "can't find codec2_create" try:
|
||||
|
||||
david@cool:~/asterisk-1.8.9.0$ touch codecs/codec_codec2.c
|
||||
david@cool:~/asterisk-1.8.9.0$ make ASTLDFLAGS=-lcodec2
|
||||
david@cool:~/asterisk-1.8.9.0$ sudo cp codecs/codec_codec2.so /usr/lib/asterisk/modules
|
||||
david@cool:~/asterisk-1.8.9.0$ sudo asterisk -vvvcn
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
--- /home/david/asterisk-1.8.9.0-orig/include/asterisk/frame.h 2011-12-23 05:08:46.000000000 +1030
|
||||
+++ /home/david/asterisk-1.8.9.0-codec2/include/asterisk/frame.h 2012-03-27 13:16:55.623452431 +1030
|
||||
@@ -299,6 +299,7 @@
|
||||
#define AST_FORMAT_G719 (1ULL << 32)
|
||||
/*! SpeeX Wideband (16kHz) Free Compression */
|
||||
#define AST_FORMAT_SPEEX16 (1ULL << 33)
|
||||
+#define AST_FORMAT_CODEC2 (1ULL << 34)
|
||||
/*! Raw mu-law data (G.711) */
|
||||
#define AST_FORMAT_TESTLAW (1ULL << 47)
|
||||
/*! Reserved bit - do not use */
|
||||
--- /home/david/asterisk-1.8.9.0-orig/main/frame.c 2010-06-18 02:53:43.000000000 +0930
|
||||
+++ /home/david/asterisk-1.8.9.0-codec2/main/frame.c 2012-03-28 15:16:16.975581316 +1030
|
||||
@@ -102,6 +102,7 @@
|
||||
{ AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
|
||||
{ AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
|
||||
{ AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
|
||||
+ { AST_FORMAT_CODEC2, "codec2", 8000, "Codec 2", 7, 20, 20, 20, 20 }, /*!< codec_codec2.c */
|
||||
{ AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
|
||||
{ AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
|
||||
{ AST_FORMAT_SPEEX16, "speex16", 16000, "SpeeX 16khz", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
|
||||
@@ -1475,6 +1476,9 @@
|
||||
samples = 22 * 8;
|
||||
samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
|
||||
break;
|
||||
+ case AST_FORMAT_CODEC2:
|
||||
+ samples = 160 * (f->datalen / 7);
|
||||
+ break;
|
||||
case AST_FORMAT_ULAW:
|
||||
case AST_FORMAT_ALAW:
|
||||
case AST_FORMAT_TESTLAW:
|
||||
@@ -1519,6 +1523,9 @@
|
||||
case AST_FORMAT_GSM:
|
||||
len = (samples / 160) * 33;
|
||||
break;
|
||||
+ case AST_FORMAT_CODEC2:
|
||||
+ len = (samples / 160) * 7;
|
||||
+ break;
|
||||
case AST_FORMAT_G729A:
|
||||
len = samples / 8;
|
||||
break;
|
||||
--- /home/david/asterisk-1.8.9.0-orig/main/channel.c 2011-12-17 10:21:13.000000000 +1030
|
||||
+++ /home/david/asterisk-1.8.9.0-codec2/main/channel.c 2012-03-28 15:05:22.395293391 +1030
|
||||
@@ -1075,6 +1075,7 @@
|
||||
/*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
|
||||
to use it */
|
||||
AST_FORMAT_LPC10,
|
||||
+ AST_FORMAT_CODEC2,
|
||||
/*! G.729a is faster than 723 and slightly less expensive */
|
||||
AST_FORMAT_G729A,
|
||||
/*! Down to G.723.1 which is proprietary but at least designed for voice */
|
||||
--- /home/david/asterisk-1.8.9.0-orig/main/rtp_engine.c 2011-12-30 01:43:03.000000000 +1030
|
||||
+++ /home/david/asterisk-1.8.9.0-codec2/main/rtp_engine.c 2012-03-28 16:42:02.880872891 +1030
|
||||
@@ -101,6 +101,7 @@
|
||||
{{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
|
||||
{{1, AST_FORMAT_SLINEAR16}, "audio", "L16", 16000},
|
||||
{{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
|
||||
+ {{1, AST_FORMAT_CODEC2}, "audio", "CODEC2", 8000},
|
||||
{{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
|
||||
{{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
|
||||
{{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
|
||||
@@ -178,6 +179,7 @@
|
||||
[117] = {1, AST_FORMAT_SPEEX16},
|
||||
[118] = {1, AST_FORMAT_SLINEAR16}, /* 16 Khz signed linear */
|
||||
[121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
|
||||
+ [121] = {1, AST_FORMAT_CODEC2},
|
||||
};
|
||||
|
||||
int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* Codec 2 module for Asterisk.
|
||||
*
|
||||
* Credit: codec_gsm.c used as a starting point.
|
||||
*
|
||||
* Copyright (C) 2012 Ed W and David Rowe
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Translate between signed linear and Codec 2
|
||||
*
|
||||
* \ingroup codecs
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
#include <codec2.h>
|
||||
|
||||
#define BUFFER_SAMPLES 8000
|
||||
#define CODEC2_SAMPLES 160
|
||||
#define CODEC2_FRAME_LEN 7
|
||||
|
||||
/* Sample frame data */
|
||||
|
||||
#include "asterisk/slin.h"
|
||||
#include "ex_codec2.h"
|
||||
|
||||
struct codec2_translator_pvt { /* both codec2tolin and codec2togsm */
|
||||
struct CODEC2 *codec2;
|
||||
short buf[BUFFER_SAMPLES]; /* lintocodec2, temporary storage */
|
||||
};
|
||||
|
||||
static int codec2_new(struct ast_trans_pvt *pvt)
|
||||
{
|
||||
struct codec2_translator_pvt *tmp = pvt->pvt;
|
||||
|
||||
tmp->codec2 = codec2_create(CODEC2_MODE_2400);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief decode and store in outbuf. */
|
||||
static int codec2tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct codec2_translator_pvt *tmp = pvt->pvt;
|
||||
int x;
|
||||
int16_t *dst = pvt->outbuf.i16;
|
||||
int flen = CODEC2_FRAME_LEN;
|
||||
|
||||
for (x=0; x < f->datalen; x += flen) {
|
||||
unsigned char *src;
|
||||
int len;
|
||||
len = CODEC2_SAMPLES;
|
||||
src = f->data.ptr + x;
|
||||
|
||||
codec2_decode(tmp->codec2, dst + pvt->samples, src);
|
||||
|
||||
pvt->samples += CODEC2_SAMPLES;
|
||||
pvt->datalen += 2 * CODEC2_SAMPLES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief store samples into working buffer for later decode */
|
||||
static int lintocodec2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct codec2_translator_pvt *tmp = pvt->pvt;
|
||||
|
||||
if (pvt->samples + f->samples > BUFFER_SAMPLES) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
|
||||
pvt->samples += f->samples;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief encode and produce a frame */
|
||||
static struct ast_frame *lintocodec2_frameout(struct ast_trans_pvt *pvt)
|
||||
{
|
||||
struct codec2_translator_pvt *tmp = pvt->pvt;
|
||||
int datalen = 0;
|
||||
int samples = 0;
|
||||
|
||||
/* We can't work on anything less than a frame in size */
|
||||
if (pvt->samples < CODEC2_SAMPLES)
|
||||
return NULL;
|
||||
while (pvt->samples >= CODEC2_SAMPLES) {
|
||||
/* Encode a frame of data */
|
||||
codec2_encode(tmp->codec2, (unsigned char*)(pvt->outbuf.c + datalen), tmp->buf + samples);
|
||||
datalen += CODEC2_FRAME_LEN;
|
||||
samples += CODEC2_SAMPLES;
|
||||
pvt->samples -= CODEC2_SAMPLES;
|
||||
}
|
||||
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (pvt->samples)
|
||||
memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
|
||||
|
||||
return ast_trans_frameout(pvt, datalen, samples);
|
||||
}
|
||||
|
||||
static void codec2_destroy_stuff(struct ast_trans_pvt *pvt)
|
||||
{
|
||||
struct codec2_translator_pvt *tmp = pvt->pvt;
|
||||
if (tmp->codec2)
|
||||
codec2_destroy(tmp->codec2);
|
||||
}
|
||||
|
||||
static struct ast_translator codec2tolin = {
|
||||
.name = "codec2tolin",
|
||||
.srcfmt = AST_FORMAT_CODEC2,
|
||||
.dstfmt = AST_FORMAT_SLINEAR,
|
||||
.newpvt = codec2_new,
|
||||
.framein = codec2tolin_framein,
|
||||
.destroy = codec2_destroy_stuff,
|
||||
.sample = codec2_sample,
|
||||
.buffer_samples = BUFFER_SAMPLES,
|
||||
.buf_size = BUFFER_SAMPLES * 2,
|
||||
.desc_size = sizeof (struct codec2_translator_pvt ),
|
||||
};
|
||||
|
||||
static struct ast_translator lintocodec2 = {
|
||||
.name = "lintocodec2",
|
||||
.srcfmt = AST_FORMAT_SLINEAR,
|
||||
.dstfmt = AST_FORMAT_CODEC2,
|
||||
.newpvt = codec2_new,
|
||||
.framein = lintocodec2_framein,
|
||||
.frameout = lintocodec2_frameout,
|
||||
.destroy = codec2_destroy_stuff,
|
||||
.sample = slin8_sample,
|
||||
.desc_size = sizeof (struct codec2_translator_pvt ),
|
||||
.buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1)/CODEC2_SAMPLES,
|
||||
};
|
||||
|
||||
/*! \brief standard module glue */
|
||||
static int reload(void)
|
||||
{
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_translator(&lintocodec2);
|
||||
if (!res)
|
||||
res = ast_unregister_translator(&codec2tolin);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_translator(&codec2tolin);
|
||||
if (!res)
|
||||
res=ast_register_translator(&lintocodec2);
|
||||
else
|
||||
ast_unregister_translator(&codec2tolin);
|
||||
if (res)
|
||||
return AST_MODULE_LOAD_FAILURE;
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Codec 2 Coder/Decoder",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload,
|
||||
);
|
|
@ -1,28 +0,0 @@
|
|||
/*! \file
|
||||
* \brief 8-bit raw data
|
||||
*
|
||||
* Copyright (C) 2012, 2012 Ed W and David Rowe
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static uint8_t ex_codec2[] = {
|
||||
0x3e,0x06,0x4a,0xbb,0x9e,0x40,0xc0
|
||||
};
|
||||
|
||||
static struct ast_frame *codec2_sample(void)
|
||||
{
|
||||
static struct ast_frame f = {
|
||||
.frametype = AST_FRAME_VOICE,
|
||||
.subclass.codec = AST_FORMAT_CODEC2,
|
||||
.datalen = sizeof(ex_codec2),
|
||||
.samples = CODEC2_SAMPLES,
|
||||
.mallocd = 0,
|
||||
.offset = 0,
|
||||
.src = __PRETTY_FUNCTION__,
|
||||
.data.ptr = ex_codec2,
|
||||
};
|
||||
|
||||
return &f;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Create patch for Codec 2 support inside Asterisk
|
||||
|
||||
ORIG=~/asterisk-1.8.9.0-orig
|
||||
CODEC2=~/asterisk-1.8.9.0-codec2
|
||||
diff -ruN $ORIG/include/asterisk/frame.h $CODEC2/include/asterisk/frame.h > asterisk-codec2.patch
|
||||
diff -ruN $ORIG/main/frame.c $CODEC2/main/frame.c >> asterisk-codec2.patch
|
||||
diff -ruN $ORIG/main/channel.c $CODEC2/main/channel.c >> asterisk-codec2.patch
|
||||
diff -ruN $ORIG/main/rtp_engine.c $CODEC2/main/rtp_engine.c >> asterisk-codec2.patch
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.59])
|
||||
AC_INIT(codec2, 0.2, david@rowetel.com)
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Checks for libraries.
|
||||
# FIXME: Replace `main' with a function in `-lm':
|
||||
AC_CHECK_LIB([m], [main])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdlib.h string.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MALLOC
|
||||
AC_CHECK_FUNCS([floor pow sqrt])
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile unittest/Makefile])
|
||||
AC_OUTPUT
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
|
||||
$srcpath/configure "$@" --disable-shared --with-pic
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 133 B |
Binary file not shown.
Before Width: | Height: | Size: 552 B |
Binary file not shown.
Before Width: | Height: | Size: 135 B |
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB |
|
@ -1 +0,0 @@
|
|||
s(n)=A_1cos(\omega_0+\phi_1)+A_2cos(2\omega_0+\phi_2)+...+A_Lcos(L\omega_0+\phi_L)
|
|
@ -1,19 +0,0 @@
|
|||
# Requires FLTK 1.3 & Portaudio V19
|
||||
|
||||
FLTK_VER = $(shell fltk-config --api-version)
|
||||
ifneq ($(FLTK_VER),1.3)
|
||||
$(error Must use FLTK version 1.3, you have $(FLTK_VER))
|
||||
endif
|
||||
|
||||
FLTK_CFLAGS += $(shell fltk-config --ldstaticflags)
|
||||
CFLAGS = -O3 -g -Wall
|
||||
LIBS = ../src/.libs/libcodec2.a -lm -lrt -lportaudio -pthread
|
||||
LC2POC_C = fl_fdmdv.cxx
|
||||
|
||||
all: fl_fdmdv
|
||||
|
||||
fl_fdmdv: Makefile $(LC2POC_C)
|
||||
g++ $(LC2POC_C) -I../src/ -o fl_fdmdv $(CFLAGS) $(FLTK_CFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f fl_fdmdv
|
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
|||
README.txt
|
||||
For codec2/octave directory
|
||||
Created 24 June 2012 by David Rowe
|
||||
|
||||
1/ To support some of the Octave scripts (in particular fdmdv) in this
|
||||
directory the following Octave packages need to be installed:
|
||||
|
||||
control image miscellaneous optim signal specfun struct
|
||||
|
||||
2/ Download these tar balls from:
|
||||
|
||||
http://octave.sourceforge.net/packages.php
|
||||
|
||||
3/ Install each package from the Octave command line with:
|
||||
|
||||
octave:3> pkg install package_file_name.tar.gz
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
% av_imp.m
|
||||
% David Rowe Aug 2012
|
||||
% Averages the impulse response samples
|
||||
|
||||
function imp = av_imp(imp_filename, period_in_secs, st, en)
|
||||
f = fopen(imp_filename,"rb");
|
||||
s = fread(f, Inf, "short")';
|
||||
|
||||
Fs = 8000;
|
||||
n = period_in_secs * Fs;
|
||||
|
||||
[r c] = size(s);
|
||||
|
||||
imp = zeros(1,n);
|
||||
for i=1:n:c-n
|
||||
imp = imp + s(i:i+n-1);
|
||||
endfor
|
||||
|
||||
% user supplies start and end samples after viweing plot
|
||||
|
||||
if (nargin == 4)
|
||||
imp = imp(st:en);
|
||||
end
|
||||
|
||||
% normalise
|
||||
|
||||
imp /= sqrt(sum(imp .^ 2));
|
||||
|
||||
[h w] = freqz(imp, 1, 4000);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(imp);
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(10*log10(abs(h)))
|
||||
subplot(212)
|
||||
plot(angle(h))
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
% cbphase.m
|
||||
% David Rowe Aug 2012
|
||||
% Used to experiment with critical band phase perception and smoothing
|
||||
|
||||
function cbphase
|
||||
|
||||
Wo = 100.0*pi/4000;
|
||||
L = floor(pi/Wo);
|
||||
|
||||
A = zeros(1,L);
|
||||
phi = zeros(1,L);
|
||||
|
||||
% three harmonics in this band
|
||||
|
||||
b = 4; a = b-1; c = b+1;
|
||||
|
||||
% set up phases and mags for 2nd order system (see phasesecord.m)
|
||||
|
||||
wres = b*Wo;
|
||||
phi(a) = 3*pi/4 + wres;
|
||||
phi(b) = pi/2 + wres;
|
||||
phi(c) = pi/4 + wres;
|
||||
|
||||
A(a) = 0.707;
|
||||
A(b) = 1;
|
||||
A(c) = 0.707;
|
||||
|
||||
% add linear component
|
||||
|
||||
phi(1) = pi;
|
||||
phi(2:L) = phi(2:L) + (2:L)*phi(1);
|
||||
phi = phi - 2*pi*(floor(phi/(2*pi)) + 0.5);
|
||||
|
||||
N = 16000;
|
||||
Nplot = 250;
|
||||
s = zeros(1,N);
|
||||
|
||||
for m=a:c
|
||||
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m));
|
||||
s = s + s_m;
|
||||
endfor
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
plot((1:L)*Wo*4000/pi, A,'+');
|
||||
subplot(212)
|
||||
plot((1:L)*Wo*4000/pi, phi,'+');
|
||||
|
||||
%v = A(a)*exp(j*phi(a)) + A(b)*exp(j*phi(b)) + A(c)*exp(j*phi(c));
|
||||
%compass(v,"r")
|
||||
%hold off;
|
||||
|
||||
% est phi1
|
||||
|
||||
diff = phi(b) - phi(a)
|
||||
sumi = sin(diff);
|
||||
sumr = cos(diff);
|
||||
diff = phi(c) - phi(b)
|
||||
sumi += sin(diff);
|
||||
sumr += cos(diff);
|
||||
phi1_ = atan2(sumi, sumr)
|
||||
s_v = cos(Wo*(0:(N-1)) + phi1_);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(s(1:Nplot));
|
||||
hold on;
|
||||
plot(s_v(1:Nplot),"r");
|
||||
hold off;
|
||||
|
||||
% build (hopefully) perceptually similar phase
|
||||
|
||||
phi_(a) = a*phi1_;
|
||||
phi_(b) = b*phi1_;
|
||||
phi_(c) = c*phi1_;
|
||||
|
||||
s_ = zeros(1,N);
|
||||
|
||||
for m=a:c
|
||||
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi_(m));
|
||||
s_ = s_ + s_m;
|
||||
endfor
|
||||
|
||||
subplot(212)
|
||||
plot(s_(1:Nplot));
|
||||
|
||||
gain = 8000;
|
||||
fs=fopen("orig_ph.raw","wb");
|
||||
fwrite(fs,gain*s,"short");
|
||||
fclose(fs);
|
||||
fs=fopen("mod_ph.raw","wb");
|
||||
fwrite(fs,gain*s_,"short");
|
||||
fclose(fs);
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% codec2_demo.m
|
||||
|
||||
% Designed as an educational tool to explain the operation of Codec 2
|
||||
% for conference and user group presentations on a projector. An
|
||||
% alternative to static overhead slides.
|
||||
%
|
||||
% Derived from codec2-dev/octave/plamp.m
|
||||
%
|
||||
% usage:
|
||||
% octave:1> plamp("../src/hts2a",40)
|
||||
%
|
||||
% Then press:
|
||||
% c - to cycle through the wavform being displayed on the figure
|
||||
% n - next frame
|
||||
% b - back one frame
|
||||
%
|
||||
% tip: hold down n or b to animate the display
|
||||
%
|
||||
% The text files used as input are generated using c2sim:
|
||||
%
|
||||
% /codec2-dev/src$ c2sim ../raw/hts2a.raw --dump hts2a
|
||||
%
|
||||
% The Codec 2 README explains how to build c2sim with dump files
|
||||
% enabled.
|
||||
|
||||
function codec2_demo(samname, f)
|
||||
|
||||
sn_name = strcat(samname,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
sw_name = strcat(samname,"_sw.txt");
|
||||
Sw = load(sw_name);
|
||||
|
||||
model_name = strcat(samname,"_model.txt");
|
||||
model = load(model_name);
|
||||
|
||||
figure(1);
|
||||
|
||||
k = ' ';
|
||||
wf = "Sn";
|
||||
do
|
||||
|
||||
if strcmp(wf,"Sn")
|
||||
clf;
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
plot(s);
|
||||
axis([1 length(s) -20000 20000]);
|
||||
end
|
||||
|
||||
if (strcmp(wf,"Sw"))
|
||||
clf;
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
end
|
||||
|
||||
if strcmp(wf,"SwAm")
|
||||
Wo = model(f,1);
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
hold on;
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Am),"+;Am;r");
|
||||
axis([1 4000 -10 80]);
|
||||
hold off;
|
||||
end
|
||||
|
||||
if strcmp(wf,"Am")
|
||||
Wo = model(f,1);
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Am),"+;Am;r");
|
||||
axis([1 4000 -10 80]);
|
||||
end
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back w-cycle window q-quit", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
end
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
end
|
||||
if (k == 'w')
|
||||
if strcmp(wf,"Sn")
|
||||
next_wf = "Sw";
|
||||
end
|
||||
if strcmp(wf,"Sw")
|
||||
next_wf = "SwAm";
|
||||
end
|
||||
if strcmp(wf,"SwAm")
|
||||
next_wf = "Am";
|
||||
end
|
||||
if strcmp(wf,"Am")
|
||||
next_wf = "Sn";
|
||||
end
|
||||
wf = next_wf;
|
||||
end
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,54 +0,0 @@
|
|||
% cspec.m
|
||||
% David Rowe Aug 2012
|
||||
% Used to compare spectromgrams while experimenting with phase
|
||||
|
||||
function cspec(s1,s2)
|
||||
f1 = fopen(s1,"rb");
|
||||
s1 = fread(f1,Inf,"short");
|
||||
f2 = fopen(s2,"rb");
|
||||
s2 = fread(f2,Inf,"short");
|
||||
|
||||
Fs = 8000;
|
||||
spec_win = 512;
|
||||
|
||||
state = 's1';
|
||||
do
|
||||
if strcmp(state,'s1')
|
||||
spec(s1,Fs,spec_win);
|
||||
%title(s1);
|
||||
end
|
||||
if strcmp(state,'s2')
|
||||
spec(s2,Fs,spec_win);
|
||||
%title(s2);
|
||||
end
|
||||
if strcmp(state,'diff')
|
||||
spec(s1-s2,Fs,spec_win);
|
||||
%title("difference");
|
||||
end
|
||||
|
||||
printf("\rstate: %s space-toggle d-diff q-quit", state);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
|
||||
if k == ' '
|
||||
if strcmp(state,"diff")
|
||||
next_state = 's1';
|
||||
end
|
||||
if strcmp(state,"s1")
|
||||
next_state = 's2';
|
||||
end
|
||||
if strcmp(state,'s2')
|
||||
next_state = 's1';
|
||||
end
|
||||
end
|
||||
|
||||
if k == 'd'
|
||||
next_state = 'diff';
|
||||
end
|
||||
|
||||
state = next_state;
|
||||
until (k == 'q')
|
||||
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,935 +0,0 @@
|
|||
% fdmdv.m
|
||||
%
|
||||
% Functions that implement a Frequency Divison Multiplexed Modem for
|
||||
% Digital Voice (FDMDV) over HF channels.
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
% reqd to mak sure we get same random bits at mod and demod
|
||||
|
||||
rand('state',1);
|
||||
randn('state',1);
|
||||
|
||||
% Constants
|
||||
|
||||
global Fs = 8000; % sample rate in Hz
|
||||
global T = 1/Fs; % sample period in seconds
|
||||
global Rs = 50; % symbol rate in Hz
|
||||
global Nc = 14; % number of carriers
|
||||
global Nb = 2; % Bits/symbol for QPSK modulation
|
||||
global Rb = Nc*Rs*Nb; % bit rate
|
||||
global M = Fs/Rs; % oversampling factor
|
||||
global Nsym = 6; % number of symbols to filter over
|
||||
global Fsep = 75; % Separation between carriers (Hz)
|
||||
global Fcentre = 1200; % Centre frequency, Nc/2 carriers below this, N/c carriers above (Hz)
|
||||
global Nt = 5; % number of symbols we estimate timing over
|
||||
global P = 4; % oversample factor used for rx symbol filtering
|
||||
global Nfilter = Nsym*M;
|
||||
global Nfiltertiming = M+Nfilter+M;
|
||||
alpha = 0.5;
|
||||
global snr_coeff = 0.9 % SNR est averaging filter coeff
|
||||
|
||||
% root raised cosine (Root Nyquist) filter
|
||||
|
||||
global gt_alpha5_root;
|
||||
gt_alpha5_root = gen_rn_coeffs(alpha, T, Rs, Nsym, M);
|
||||
|
||||
|
||||
% Functions ----------------------------------------------------
|
||||
|
||||
|
||||
% generate Nc+1 QPSK symbols from vector of (1,Nc*Nb) input bits. The
|
||||
% Nc+1 symbol is the +1 -1 +1 .... BPSK sync carrier
|
||||
|
||||
function tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, modulation)
|
||||
global Nc;
|
||||
global Nb;
|
||||
global pilot_bit;
|
||||
|
||||
% re-arrange as (Nc,Nb) matrix
|
||||
|
||||
tx_bits_matrix = zeros(Nc,Nb);
|
||||
tx_bits_matrix(1:Nc,1) = tx_bits(1:Nb:Nb*Nc);
|
||||
tx_bits_matrix(1:Nc,2) = tx_bits(2:Nb:Nb*Nc);
|
||||
|
||||
if (strcmp(modulation,'dqpsk'))
|
||||
|
||||
% map to (Nc,1) DQPSK symbols
|
||||
|
||||
for c=1:Nc
|
||||
msb = tx_bits_matrix(c,1); lsb = tx_bits_matrix(c,2);
|
||||
|
||||
if ((msb == 0) && (lsb == 0))
|
||||
tx_symbols(c) = prev_tx_symbols(c);
|
||||
endif
|
||||
if ((msb == 0) && (lsb == 1))
|
||||
tx_symbols(c) = j*prev_tx_symbols(c);
|
||||
endif
|
||||
if ((msb == 1) && (lsb == 0))
|
||||
tx_symbols(c) = -prev_tx_symbols(c);
|
||||
endif
|
||||
if ((msb == 1) && (lsb == 1))
|
||||
tx_symbols(c) = -j*prev_tx_symbols(c);
|
||||
endif
|
||||
end
|
||||
else
|
||||
% QPSK mapping
|
||||
tx_symbols = -1 + 2*tx_bits_matrix(:,1) - j + 2j*tx_bits_matrix(:,2);
|
||||
endif
|
||||
|
||||
% +1 -1 +1 -1 BPSK sync carrier, once filtered becomes two spectral
|
||||
% lines at +/- Rs/2
|
||||
|
||||
if pilot_bit
|
||||
tx_symbols(Nc+1) = -prev_tx_symbols(Nc+1);
|
||||
else
|
||||
tx_symbols(Nc+1) = prev_tx_symbols(Nc+1);
|
||||
end
|
||||
if pilot_bit
|
||||
pilot_bit = 0;
|
||||
else
|
||||
pilot_bit = 1;
|
||||
end
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Given Nc*Nb bits construct M samples (1 symbol) of Nc filtered
|
||||
% symbols streams
|
||||
|
||||
function tx_baseband = tx_filter(tx_symbols)
|
||||
global Nc;
|
||||
global M;
|
||||
global tx_filter_memory;
|
||||
global Nfilter;
|
||||
global gt_alpha5_root;
|
||||
|
||||
tx_baseband = zeros(Nc+1,M);
|
||||
|
||||
% tx filter each symbol, generate M filtered output samples for each symbol.
|
||||
% Efficient polyphase filter techniques used as tx_filter_memory is sparse
|
||||
|
||||
tx_filter_memory(:,Nfilter) = sqrt(2)/2*tx_symbols;
|
||||
|
||||
for i=1:M
|
||||
tx_baseband(:,i) = M*tx_filter_memory(:,M:M:Nfilter) * gt_alpha5_root(M-i+1:M:Nfilter)';
|
||||
end
|
||||
tx_filter_memory(:,1:Nfilter-M) = tx_filter_memory(:,M+1:Nfilter);
|
||||
tx_filter_memory(:,Nfilter-M+1:Nfilter) = zeros(Nc+1,M);
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Construct FDM signal by frequency shifting each filtered symbol
|
||||
% stream. Returns complex signal so we can apply frequency offsets
|
||||
% easily.
|
||||
|
||||
function tx_fdm = fdm_upconvert(tx_filt)
|
||||
global Fs;
|
||||
global M;
|
||||
global Nc;
|
||||
global Fsep;
|
||||
global phase_tx;
|
||||
global freq;
|
||||
|
||||
tx_fdm = zeros(1,M);
|
||||
|
||||
% Nc/2 tones below centre freq
|
||||
|
||||
for c=1:Nc/2
|
||||
for i=1:M
|
||||
phase_tx(c) = phase_tx(c) * freq(c);
|
||||
tx_fdm(i) = tx_fdm(i) + tx_filt(c,i)*phase_tx(c);
|
||||
end
|
||||
end
|
||||
|
||||
% Nc/2 tones above centre freq
|
||||
|
||||
for c=Nc/2+1:Nc
|
||||
for i=1:M
|
||||
phase_tx(c) = phase_tx(c) * freq(c);
|
||||
tx_fdm(i) = tx_fdm(i) + tx_filt(c,i)*phase_tx(c);
|
||||
end
|
||||
end
|
||||
|
||||
% add centre pilot tone
|
||||
|
||||
c = Nc+1;
|
||||
for i=1:M
|
||||
phase_tx(c) = phase_tx(c) * freq(c);
|
||||
pilot(i) = 2*tx_filt(c,i)*phase_tx(c);
|
||||
tx_fdm(i) = tx_fdm(i) + pilot(i);
|
||||
end
|
||||
|
||||
% Scale such that total Carrier power C of real(tx_fdm) = Nc. This
|
||||
% excludes the power of the pilot tone.
|
||||
% We return the complex (single sided) signal to make frequency
|
||||
% shifting for the purpose of testing easier
|
||||
|
||||
tx_fdm = 2*tx_fdm;
|
||||
endfunction
|
||||
|
||||
|
||||
% Frequency shift each modem carrier down to Nc+1 baseband signals
|
||||
|
||||
function rx_baseband = fdm_downconvert(rx_fdm, nin)
|
||||
global Fs;
|
||||
global M;
|
||||
global Nc;
|
||||
global Fsep;
|
||||
global phase_rx;
|
||||
global freq;
|
||||
|
||||
rx_baseband = zeros(1,nin);
|
||||
|
||||
% Nc/2 tones below centre freq
|
||||
|
||||
for c=1:Nc/2
|
||||
for i=1:nin
|
||||
phase_rx(c) = phase_rx(c) * freq(c);
|
||||
rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)';
|
||||
end
|
||||
end
|
||||
|
||||
% Nc/2 tones above centre freq
|
||||
|
||||
for c=Nc/2+1:Nc
|
||||
for i=1:nin
|
||||
phase_rx(c) = phase_rx(c) * freq(c);
|
||||
rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)';
|
||||
end
|
||||
end
|
||||
|
||||
% Pilot
|
||||
|
||||
c = Nc+1;
|
||||
for i=1:nin
|
||||
phase_rx(c) = phase_rx(c) * freq(c);
|
||||
rx_baseband(c,i) = rx_fdm(i)*phase_rx(c)';
|
||||
end
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Receive filter each baseband signal at oversample rate P
|
||||
|
||||
function rx_filt = rx_filter(rx_baseband, nin)
|
||||
global Nc;
|
||||
global M;
|
||||
global P;
|
||||
global rx_filter_memory;
|
||||
global Nfilter;
|
||||
global gt_alpha5_root;
|
||||
global Fsep;
|
||||
|
||||
rx_filt = zeros(Nc+1,nin*P/M);
|
||||
|
||||
% rx filter each symbol, generate P filtered output samples for each symbol.
|
||||
% Note we keep memory at rate M, it's just the filter output at rate P
|
||||
|
||||
N=M/P;
|
||||
j=1;
|
||||
for i=1:N:nin
|
||||
rx_filter_memory(:,Nfilter-N+1:Nfilter) = rx_baseband(:,i:i-1+N);
|
||||
rx_filt(:,j) = rx_filter_memory * gt_alpha5_root';
|
||||
rx_filter_memory(:,1:Nfilter-N) = rx_filter_memory(:,1+N:Nfilter);
|
||||
j+=1;
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
% LPF and peak pick part of freq est, put in a function as we call it twice
|
||||
|
||||
function [foff imax pilot_lpf S] = lpf_peak_pick(pilot_baseband, pilot_lpf, nin)
|
||||
global M;
|
||||
global Npilotlpf;
|
||||
global Npilotcoeff;
|
||||
global Fs;
|
||||
global Mpilotfft;
|
||||
global pilot_coeff;
|
||||
|
||||
% LPF cutoff 200Hz, so we can handle max +/- 200 Hz freq offset
|
||||
|
||||
pilot_lpf(1:Npilotlpf-nin) = pilot_lpf(nin+1:Npilotlpf);
|
||||
j = 1;
|
||||
for i = Npilotlpf-nin+1:Npilotlpf
|
||||
pilot_lpf(i) = pilot_baseband(j:j+Npilotcoeff-1) * pilot_coeff';
|
||||
j++;
|
||||
end
|
||||
|
||||
% decimate to improve DFT resolution, window and DFT
|
||||
|
||||
Mpilot = Fs/(2*200); % calc decimation rate given new sample rate is twice LPF freq
|
||||
h = hanning(Npilotlpf);
|
||||
s = pilot_lpf(1:Mpilot:Npilotlpf) .* h(1:Mpilot:Npilotlpf)';
|
||||
s = [s zeros(1,Mpilotfft-Npilotlpf/Mpilot)];
|
||||
S = fft(s, Mpilotfft);
|
||||
|
||||
% peak pick and convert to Hz
|
||||
|
||||
[imax ix] = max(S);
|
||||
r = 2*200/Mpilotfft; % maps FFT bin to frequency in Hz
|
||||
|
||||
if ix > Mpilotfft/2
|
||||
foff = (ix - Mpilotfft - 1)*r;
|
||||
else
|
||||
foff = (ix - 1)*r;
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Estimate frequency offset of FDM signal using BPSK pilot. This is quite
|
||||
% sensitive to pilot tone level wrt other carriers
|
||||
|
||||
function [foff S1 S2] = rx_est_freq_offset(rx_fdm, pilot, pilot_prev, nin)
|
||||
global M;
|
||||
global Npilotbaseband;
|
||||
global pilot_baseband1;
|
||||
global pilot_baseband2;
|
||||
global pilot_lpf1;
|
||||
global pilot_lpf2;
|
||||
|
||||
% down convert latest nin samples of pilot by multiplying by
|
||||
% ideal BPSK pilot signal we have generated locally. This
|
||||
% peak of the resulting signal is sensitive to the time shift between
|
||||
% the received and local version of the pilot, so we do it twice at
|
||||
% different time shifts and choose the maximum.
|
||||
|
||||
pilot_baseband1(1:Npilotbaseband-nin) = pilot_baseband1(nin+1:Npilotbaseband);
|
||||
pilot_baseband2(1:Npilotbaseband-nin) = pilot_baseband2(nin+1:Npilotbaseband);
|
||||
for i=1:nin
|
||||
pilot_baseband1(Npilotbaseband-nin+i) = rx_fdm(i) * conj(pilot(i));
|
||||
pilot_baseband2(Npilotbaseband-nin+i) = rx_fdm(i) * conj(pilot_prev(i));
|
||||
end
|
||||
|
||||
[foff1 max1 pilot_lpf1 S1] = lpf_peak_pick(pilot_baseband1, pilot_lpf1, nin);
|
||||
[foff2 max2 pilot_lpf2 S2] = lpf_peak_pick(pilot_baseband2, pilot_lpf2, nin);
|
||||
|
||||
if max1 > max2
|
||||
foff = foff1;
|
||||
else
|
||||
foff = foff2;
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
% Estimate optimum timing offset, re-filter receive symbols
|
||||
|
||||
function [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin)
|
||||
global M;
|
||||
global Nt;
|
||||
global Nc;
|
||||
global rx_filter_mem_timing;
|
||||
global rx_baseband_mem_timing;
|
||||
global P;
|
||||
global Nfilter;
|
||||
global Nfiltertiming;
|
||||
global gt_alpha5_root;
|
||||
|
||||
% nin adjust
|
||||
% --------------------------------
|
||||
% 120 -1 (one less rate P sample)
|
||||
% 160 0 (nominal)
|
||||
% 200 1 (one more rate P sample)
|
||||
|
||||
adjust = P - nin*P/M;
|
||||
|
||||
% update buffer of Nt rate P filtered symbols
|
||||
|
||||
rx_filter_mem_timing(:,1:(Nt-1)*P+adjust) = rx_filter_mem_timing(:,P+1-adjust:Nt*P);
|
||||
rx_filter_mem_timing(:,(Nt-1)*P+1+adjust:Nt*P) = rx_filt(:,:);
|
||||
|
||||
% sum envelopes of all carriers
|
||||
|
||||
env = sum(abs(rx_filter_mem_timing(:,:))); % use all Nc+1 carriers for timing
|
||||
%env = abs(rx_filter_mem_timing(Nc+1,:)); % just use BPSK pilot
|
||||
[n m] = size(env);
|
||||
|
||||
% The envelope has a frequency component at the symbol rate. The
|
||||
% phase of this frequency component indicates the timing. So work out
|
||||
% single DFT at frequency 2*pi/P
|
||||
|
||||
x = env * exp(-j*2*pi*(0:m-1)/P)';
|
||||
|
||||
% map phase to estimated optimum timing instant at rate M
|
||||
% the M/4 part was adjusted by experiment, I know not why....
|
||||
|
||||
rx_timing = angle(x)*M/(2*pi) + M/4;
|
||||
if (rx_timing > M)
|
||||
rx_timing -= M;
|
||||
end
|
||||
if (rx_timing < -M)
|
||||
rx_timing += M;
|
||||
end
|
||||
|
||||
% rx_baseband_mem_timing contains M + Nfilter + M samples of the
|
||||
% baseband signal at rate M this enables us to resample the filtered
|
||||
% rx symbol with M sample precision once we have rx_timing
|
||||
|
||||
rx_baseband_mem_timing(:,1:Nfiltertiming-nin) = rx_baseband_mem_timing(:,nin+1:Nfiltertiming);
|
||||
rx_baseband_mem_timing(:,Nfiltertiming-nin+1:Nfiltertiming) = rx_baseband;
|
||||
|
||||
% sample right in the middle of the timing estimator window, by filtering
|
||||
% at rate M
|
||||
|
||||
s = round(rx_timing) + M;
|
||||
rx_symbols = rx_baseband_mem_timing(:,s+1:s+Nfilter) * gt_alpha5_root';
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Phase estimation function - probably won't work over a HF channel
|
||||
% Tries to operate over a single symbol but uses phase information from
|
||||
% all Nc carriers which should increase the SNR of phase estimate.
|
||||
% Maybe phase is coherent over a couple of symbols in HF channel,not
|
||||
% sure but it's worth 3dB so worth experimenting or using coherent as
|
||||
% an option.
|
||||
|
||||
function rx_phase = rx_est_phase(prev_rx_symbols, rx_symbols)
|
||||
|
||||
% modulation strip
|
||||
|
||||
rx_phase = angle(sum(rx_symbols .^ 4))/4;
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% convert symbols back to an array of bits
|
||||
|
||||
function [rx_bits sync_bit f_err phase_difference] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation)
|
||||
global Nc;
|
||||
global Nb;
|
||||
global Nb;
|
||||
|
||||
if (strcmp(modulation,'dqpsk'))
|
||||
% extra 45 degree clockwise lets us use real and imag axis as
|
||||
% decision boundaries
|
||||
|
||||
phase_difference = zeros(Nc+1,1);
|
||||
phase_difference(1:Nc) = rx_symbols(1:Nc) .* conj(prev_rx_symbols(1:Nc)) * exp(j*pi/4);
|
||||
|
||||
% map (Nc,1) DQPSK symbols back into an (1,Nc*Nb) array of bits
|
||||
|
||||
for c=1:Nc
|
||||
d = phase_difference(c);
|
||||
if ((real(d) >= 0) && (imag(d) >= 0))
|
||||
msb = 0; lsb = 0;
|
||||
endif
|
||||
if ((real(d) < 0) && (imag(d) >= 0))
|
||||
msb = 0; lsb = 1;
|
||||
endif
|
||||
if ((real(d) < 0) && (imag(d) < 0))
|
||||
msb = 1; lsb = 0;
|
||||
endif
|
||||
if ((real(d) >= 0) && (imag(d) < 0))
|
||||
msb = 1; lsb = 1;
|
||||
endif
|
||||
rx_bits(2*(c-1)+1) = msb;
|
||||
rx_bits(2*(c-1)+2) = lsb;
|
||||
end
|
||||
|
||||
% Extract DBPSK encoded Sync bit
|
||||
|
||||
phase_difference(Nc+1,1) = rx_symbols(Nc+1) .* conj(prev_rx_symbols(Nc+1));
|
||||
if (real(phase_difference(Nc+1)) < 0)
|
||||
sync_bit = 1;
|
||||
f_err = imag(phase_difference(Nc+1));
|
||||
else
|
||||
sync_bit = 0;
|
||||
f_err = -imag(phase_difference(Nc+1));
|
||||
end
|
||||
|
||||
% pilot carrier gets an extra pi/4 rotation to make it consistent with
|
||||
% other carriers, as we need it for snr_update and scatter diagram
|
||||
|
||||
phase_difference(Nc+1) *= exp(j*pi/4);
|
||||
else
|
||||
% map (Nc,1) QPSK symbols back into an (1,Nc*Nb) array of bits
|
||||
|
||||
rx_bits(1:Nb:Nc*Nb) = real(rx_symbols) > 0;
|
||||
rx_bits(2:Nb:Nc*Nb) = imag(rx_symbols) > 0;
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% given phase differences update estimates of signal and noise levels
|
||||
|
||||
function [sig_est noise_est] = snr_update(sig_est, noise_est, phase_difference)
|
||||
global snr_coeff;
|
||||
global Nc;
|
||||
|
||||
% mag of each symbol is distance from origin, this gives us a
|
||||
% vector of mags, one for each carrier.
|
||||
|
||||
s = abs(phase_difference);
|
||||
|
||||
% signal mag estimate for each carrier is a smoothed version
|
||||
% of instantaneous magntitude, this gives us a vector of smoothed
|
||||
% mag estimates, one for each carrier.
|
||||
|
||||
sig_est = snr_coeff*sig_est + (1 - snr_coeff)*s;
|
||||
|
||||
% noise mag estimate is distance of current symbol from average
|
||||
% location of that symbol. We reflect all symbols into the first
|
||||
% quadrant for convenience.
|
||||
|
||||
refl_symbols = abs(real(phase_difference)) + j*abs(imag(phase_difference));
|
||||
n = abs(exp(j*pi/4)*sig_est - refl_symbols);
|
||||
|
||||
% noise mag estimate for each carrier is a smoothed version of
|
||||
% instantaneous noise mag, this gives us a vector of smoothed
|
||||
% noise power estimates, one for each carrier.
|
||||
|
||||
noise_est = snr_coeff*noise_est + (1 - snr_coeff)*n;
|
||||
endfunction
|
||||
|
||||
|
||||
% calculate current SNR estimate (3000Hz noise BW)
|
||||
|
||||
function snr_dB = calc_snr(sig_est, noise_est)
|
||||
global Rs;
|
||||
|
||||
% find total signal power by summing power in all carriers
|
||||
|
||||
S = sum(sig_est .^2);
|
||||
SdB = 10*log10(S);
|
||||
|
||||
% Average noise mag across all carriers and square to get an average
|
||||
% noise power. This is an estimate of the noise power in Rs = 50Hz of
|
||||
% BW (note for raised root cosine filters Rs is the noise BW of the
|
||||
% filter)
|
||||
|
||||
N50 = mean(noise_est).^2;
|
||||
N50dB = 10*log10(N50);
|
||||
|
||||
% Now multiply by (3000 Hz)/(50 Hz) to find the total noise power in
|
||||
% 3000 Hz
|
||||
|
||||
N3000dB = N50dB + 10*log10(3000/Rs);
|
||||
|
||||
snr_dB = SdB - N3000dB;
|
||||
|
||||
endfunction
|
||||
|
||||
% returns nbits from a repeating sequence of random data
|
||||
|
||||
function bits = get_test_bits(nbits)
|
||||
global Ntest_bits; % length of test sequence
|
||||
global current_test_bit;
|
||||
global test_bits;
|
||||
|
||||
for i=1:nbits
|
||||
bits(i) = test_bits(current_test_bit++);
|
||||
if (current_test_bit > Ntest_bits)
|
||||
current_test_bit = 1;
|
||||
endif
|
||||
end
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Accepts nbits from rx and attempts to sync with test_bits sequence.
|
||||
% if sync OK measures bit errors
|
||||
|
||||
function [sync bit_errors] = put_test_bits(rx_bits)
|
||||
global Ntest_bits; % length of test sequence
|
||||
global test_bits;
|
||||
global rx_test_bits_mem;
|
||||
|
||||
% Append to our memory
|
||||
|
||||
[m n] = size(rx_bits);
|
||||
rx_test_bits_mem(1:Ntest_bits-n) = rx_test_bits_mem(n+1:Ntest_bits);
|
||||
rx_test_bits_mem(Ntest_bits-n+1:Ntest_bits) = rx_bits;
|
||||
|
||||
% see how many bit errors we get when checked against test sequence
|
||||
|
||||
bit_errors = sum(xor(test_bits,rx_test_bits_mem));
|
||||
|
||||
% if less than a thresh we are aligned and in sync with test sequence
|
||||
|
||||
ber = bit_errors/Ntest_bits;
|
||||
|
||||
sync = 0;
|
||||
if (ber < 0.2)
|
||||
sync = 1;
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
% Generate M samples of DBPSK pilot signal for Freq offset estimation
|
||||
|
||||
function [pilot_fdm bit symbol filter_mem phase] = generate_pilot_fdm(bit, symbol, filter_mem, phase, freq)
|
||||
global M;
|
||||
global Nfilter;
|
||||
global gt_alpha5_root;
|
||||
|
||||
% +1 -1 +1 -1 DBPSK sync carrier, once filtered becomes two spectral
|
||||
% lines at +/- Rs/2
|
||||
|
||||
if bit
|
||||
symbol = -symbol;
|
||||
else
|
||||
symbol = symbol;
|
||||
end
|
||||
if bit
|
||||
bit = 0;
|
||||
else
|
||||
bit = 1;
|
||||
end
|
||||
|
||||
% filter DPSK symbol to create M baseband samples
|
||||
|
||||
filter_mem(Nfilter) = (sqrt(2)/2)*symbol;
|
||||
for i=1:M
|
||||
tx_baseband(i) = M*filter_mem(M:M:Nfilter) * gt_alpha5_root(M-i+1:M:Nfilter)';
|
||||
end
|
||||
filter_mem(1:Nfilter-M) = filter_mem(M+1:Nfilter);
|
||||
filter_mem(Nfilter-M+1:Nfilter) = zeros(1,M);
|
||||
|
||||
% upconvert
|
||||
|
||||
for i=1:M
|
||||
phase = phase * freq;
|
||||
pilot_fdm(i) = sqrt(2)*2*tx_baseband(i)*phase;
|
||||
end
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% Generate a 4M sample vector of DBPSK pilot signal. As the pilot signal
|
||||
% is periodic in 4M samples we can then use this vector as a look up table
|
||||
% for pilot signal generation in the demod.
|
||||
|
||||
function pilot_lut = generate_pilot_lut()
|
||||
global Nc;
|
||||
global Nfilter;
|
||||
global M;
|
||||
global freq;
|
||||
|
||||
% pilot states
|
||||
|
||||
pilot_rx_bit = 0;
|
||||
pilot_symbol = sqrt(2);
|
||||
pilot_freq = freq(Nc+1);
|
||||
pilot_phase = 1;
|
||||
pilot_filter_mem = zeros(1, Nfilter);
|
||||
%prev_pilot = zeros(M,1);
|
||||
|
||||
pilot_lut = [];
|
||||
|
||||
F=8;
|
||||
|
||||
for f=1:F
|
||||
[pilot pilot_rx_bit pilot_symbol pilot_filter_mem pilot_phase] = generate_pilot_fdm(pilot_rx_bit, pilot_symbol, pilot_filter_mem, pilot_phase, pilot_freq);
|
||||
%prev_pilot = pilot;
|
||||
pilot_lut = [pilot_lut pilot];
|
||||
end
|
||||
|
||||
% discard first 4 symbols as filter memory is filling, just keep last
|
||||
% four symbols
|
||||
|
||||
pilot_lut = pilot_lut(4*M+1:M*F);
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% grab next pilot samples for freq offset estimation at demod
|
||||
|
||||
function [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin)
|
||||
global M;
|
||||
global pilot_lut;
|
||||
|
||||
for i=1:nin
|
||||
pilot(i) = pilot_lut(pilot_lut_index);
|
||||
pilot_lut_index++;
|
||||
if pilot_lut_index > 4*M
|
||||
pilot_lut_index = 1;
|
||||
end
|
||||
prev_pilot(i) = pilot_lut(prev_pilot_lut_index);
|
||||
prev_pilot_lut_index++;
|
||||
if prev_pilot_lut_index > 4*M
|
||||
prev_pilot_lut_index = 1;
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
% Change the sample rate by a small amount, for example 1000ppm (ratio
|
||||
% = 1.001). Always returns nout samples in buf_out, but uses a
|
||||
% variable number of input samples nin to accomodate the change in
|
||||
% sample rate. nin is nominally set to nout, but may use nout +/- 2
|
||||
% samples to accomodate the different sample rates. buf_in should be
|
||||
% of length nout+6 samples to accomodate this, and buf_in should be
|
||||
% updated externally based on the nin returned each time. "ratio" is
|
||||
% Fs_in/Fs_out, for example 48048/48000 = 1.001 (+1000ppm) or
|
||||
% 47952/48000 = 0.999 (-1000ppm). Uses linear interpolation to
|
||||
% perform the resampling. This requires a highly over-sampled signal,
|
||||
% for example 48000Hz sample rate for the modem signal centred on
|
||||
% 1kHz, otherwise linear interpolation will have a low pass filter effect
|
||||
% (for example an 8000Hz sample rate for modem signal centred on 1kHz
|
||||
% would cause problems).
|
||||
|
||||
function [buf_out t nin] = resample(buf_in, t, ratio, nout)
|
||||
|
||||
for i=1:nout
|
||||
c = floor(t);
|
||||
a = t - c;
|
||||
b = 1 - a;
|
||||
buf_out(i) = buf_in(c)*b + buf_in(c+1)*a;
|
||||
t += ratio;
|
||||
end
|
||||
|
||||
t -= nout;
|
||||
|
||||
% adjust nin and t so that on next call we start with 3 < t < 4,
|
||||
% this gives us +/- 2 samples room to move before we hit start or
|
||||
% end of buf_in
|
||||
|
||||
delta = floor(t - 3);
|
||||
nin = nout + delta;
|
||||
t -= delta;
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
% freq offset state machine. Moves between acquire and track states based
|
||||
% on BPSK pilot sequence. Freq offset estimator occasionally makes mistakes
|
||||
% when used continuously. So we use it until we have acquired the BPSK pilot,
|
||||
% then switch to a more robust tracking algorithm. If we lose sync we switch
|
||||
% back to acquire mode for fast-requisition.
|
||||
|
||||
function [track state] = freq_state(sync_bit, state)
|
||||
|
||||
% acquire state, look for 6 symbol 010101 sequence from sync bit
|
||||
|
||||
next_state = state;
|
||||
if state == 0
|
||||
if sync_bit == 0
|
||||
next_state = 1;
|
||||
end
|
||||
end
|
||||
if state == 1
|
||||
if sync_bit == 1
|
||||
next_state = 2;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
if state == 2
|
||||
if sync_bit == 0
|
||||
next_state = 3;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
if state == 3
|
||||
if sync_bit == 1
|
||||
next_state = 4;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
if state == 4
|
||||
if sync_bit == 0
|
||||
next_state = 5;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
if state == 5
|
||||
if sync_bit == 1
|
||||
next_state = 6;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
|
||||
% states 6 and above are track mode, make sure we keep getting 0101 sync bit sequence
|
||||
|
||||
if state == 6
|
||||
if sync_bit == 0
|
||||
next_state = 7;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
if state == 7
|
||||
if sync_bit == 1
|
||||
next_state = 6;
|
||||
else
|
||||
next_state = 0;
|
||||
end
|
||||
end
|
||||
|
||||
state = next_state;
|
||||
if state >= 6
|
||||
track = 1;
|
||||
else
|
||||
track = 0;
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
% Save test bits to a text file in the form of a C array
|
||||
|
||||
function test_bits_file(filename)
|
||||
global test_bits;
|
||||
global Ntest_bits;
|
||||
|
||||
f=fopen(filename,"wt");
|
||||
fprintf(f,"/* Generated by test_bits_file() Octave function */\n\n");
|
||||
fprintf(f,"const int test_bits[]={\n");
|
||||
for m=1:Ntest_bits-1
|
||||
fprintf(f," %d,\n",test_bits(m));
|
||||
endfor
|
||||
fprintf(f," %d\n};\n",test_bits(Ntest_bits));
|
||||
fclose(f);
|
||||
endfunction
|
||||
|
||||
|
||||
% Saves RN filter coeffs to a text file in the form of a C array
|
||||
|
||||
function rn_file(filename)
|
||||
global gt_alpha5_root;
|
||||
global Nfilter;
|
||||
|
||||
f=fopen(filename,"wt");
|
||||
fprintf(f,"/* Generated by rn_file() Octave function */\n\n");
|
||||
fprintf(f,"const float gt_alpha5_root[]={\n");
|
||||
for m=1:Nfilter-1
|
||||
fprintf(f," %g,\n",gt_alpha5_root(m));
|
||||
endfor
|
||||
fprintf(f," %g\n};\n",gt_alpha5_root(Nfilter));
|
||||
fclose(f);
|
||||
endfunction
|
||||
|
||||
function pilot_coeff_file(filename)
|
||||
global pilot_coeff;
|
||||
global Npilotcoeff;
|
||||
|
||||
f=fopen(filename,"wt");
|
||||
fprintf(f,"/* Generated by pilot_coeff_file() Octave function */\n\n");
|
||||
fprintf(f,"const float pilot_coeff[]={\n");
|
||||
for m=1:Npilotcoeff-1
|
||||
fprintf(f," %g,\n",pilot_coeff(m));
|
||||
endfor
|
||||
fprintf(f," %g\n};\n",pilot_coeff(Npilotcoeff));
|
||||
fclose(f);
|
||||
endfunction
|
||||
|
||||
|
||||
% Saves hanning window coeffs to a text file in the form of a C array
|
||||
|
||||
function hanning_file(filename)
|
||||
global Npilotlpf;
|
||||
|
||||
h = hanning(Npilotlpf);
|
||||
|
||||
f=fopen(filename,"wt");
|
||||
fprintf(f,"/* Generated by hanning_file() Octave function */\n\n");
|
||||
fprintf(f,"const float hanning[]={\n");
|
||||
for m=1:Npilotlpf-1
|
||||
fprintf(f," %g,\n", h(m));
|
||||
endfor
|
||||
fprintf(f," %g\n};\n", h(Npilotlpf));
|
||||
fclose(f);
|
||||
endfunction
|
||||
|
||||
|
||||
function png_file(fig, pngfilename)
|
||||
figure(fig);
|
||||
|
||||
pngname = sprintf("%s.png",pngfilename);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_large.png",pngfilename);
|
||||
print(pngname, '-dpng', "-S800,600")
|
||||
endfunction
|
||||
|
||||
% Initialise ----------------------------------------------------
|
||||
|
||||
global pilot_bit;
|
||||
pilot_bit = 0; % current value of pilot bit
|
||||
|
||||
global tx_filter_memory;
|
||||
tx_filter_memory = zeros(Nc+1, Nfilter);
|
||||
global rx_filter_memory;
|
||||
rx_filter_memory = zeros(Nc+1, Nfilter);
|
||||
|
||||
% phasors used for up and down converters
|
||||
|
||||
global freq;
|
||||
freq = zeros(Nc+1,1);
|
||||
for c=1:Nc/2
|
||||
carrier_freq = (-Nc/2 - 1 + c)*Fsep + Fcentre;
|
||||
freq(c) = exp(j*2*pi*carrier_freq/Fs);
|
||||
end
|
||||
for c=Nc/2+1:Nc
|
||||
carrier_freq = (-Nc/2 + c)*Fsep + Fcentre;
|
||||
freq(c) = exp(j*2*pi*carrier_freq/Fs);
|
||||
end
|
||||
|
||||
freq(Nc+1) = exp(j*2*pi*Fcentre/Fs);
|
||||
|
||||
% Spread initial FDM carrier phase out as far as possible. This
|
||||
% helped PAPR for a few dB. We don't need to adjust rx phase as DQPSK
|
||||
% takes care of that.
|
||||
|
||||
global phase_tx;
|
||||
%phase_tx = ones(Nc+1,1);
|
||||
phase_tx = exp(j*2*pi*(0:Nc)/(Nc+1));
|
||||
global phase_rx;
|
||||
phase_rx = ones(Nc+1,1);
|
||||
|
||||
% Freq offset estimator constants
|
||||
|
||||
global Mpilotfft = 256;
|
||||
global Npilotcoeff = 30; % number of pilot LPF coeffs
|
||||
global pilot_coeff = fir1(Npilotcoeff-1, 200/(Fs/2))'; % 200Hz LPF
|
||||
global Npilotbaseband = Npilotcoeff + M + M/P; % number of pilot baseband samples reqd for pilot LPF
|
||||
global Npilotlpf = 4*M; % number of samples we DFT pilot over, pilot est window
|
||||
|
||||
% pilot LUT, used for copy of pilot at rx
|
||||
|
||||
global pilot_lut;
|
||||
pilot_lut = generate_pilot_lut();
|
||||
pilot_lut_index = 1;
|
||||
prev_pilot_lut_index = 3*M+1;
|
||||
|
||||
% Freq offset estimator states
|
||||
|
||||
global pilot_baseband1;
|
||||
global pilot_baseband2;
|
||||
pilot_baseband1 = zeros(1, Npilotbaseband); % pilot baseband samples
|
||||
pilot_baseband2 = zeros(1, Npilotbaseband); % pilot baseband samples
|
||||
global pilot_lpf1
|
||||
global pilot_lpf2
|
||||
pilot_lpf1 = zeros(1, Npilotlpf); % LPF pilot samples
|
||||
pilot_lpf2 = zeros(1, Npilotlpf); % LPF pilot samples
|
||||
|
||||
% Timing estimator states
|
||||
|
||||
global rx_filter_mem_timing;
|
||||
rx_filter_mem_timing = zeros(Nc+1, Nt*P);
|
||||
global rx_baseband_mem_timing;
|
||||
rx_baseband_mem_timing = zeros(Nc+1, Nfiltertiming);
|
||||
|
||||
% Test bit stream constants
|
||||
|
||||
global Ntest_bits = Nc*Nb*4; % length of test sequence
|
||||
global test_bits = rand(1,Ntest_bits) > 0.5;
|
||||
|
||||
% Test bit stream state variables
|
||||
|
||||
global current_test_bit = 1;
|
||||
current_test_bit = 1;
|
||||
global rx_test_bits_mem;
|
||||
rx_test_bits_mem = zeros(1,Ntest_bits);
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
% fdmdv_demod.m
|
||||
%
|
||||
% Demodulator function for FDMDV modem (Octave version). Requires
|
||||
% 8kHz sample rate raw files as input
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
function fdmdv_demod(rawfilename, nbits, pngname)
|
||||
|
||||
fdmdv; % include modem code
|
||||
|
||||
modulation = 'dqpsk';
|
||||
|
||||
fin = fopen(rawfilename, "rb");
|
||||
gain = 1000;
|
||||
frames = nbits/(Nc*Nb);
|
||||
|
||||
prev_rx_symbols = ones(Nc+1,1);
|
||||
foff_phase = 1;
|
||||
|
||||
% BER stats
|
||||
|
||||
total_bit_errors = 0;
|
||||
total_bits = 0;
|
||||
bit_errors_log = [];
|
||||
sync_log = [];
|
||||
test_frame_sync_log = [];
|
||||
test_frame_sync_state = 0;
|
||||
|
||||
% SNR states
|
||||
|
||||
sig_est = zeros(Nc+1,1);
|
||||
noise_est = zeros(Nc+1,1);
|
||||
|
||||
% logs of various states for plotting
|
||||
|
||||
rx_symbols_log = [];
|
||||
rx_timing_log = [];
|
||||
foff_log = [];
|
||||
rx_fdm_log = [];
|
||||
snr_est_log = [];
|
||||
|
||||
% misc states
|
||||
|
||||
nin = M; % timing correction for sample rate differences
|
||||
foff = 0;
|
||||
track_log = [];
|
||||
track = 0;
|
||||
fest_state = 0;
|
||||
|
||||
% Main loop ----------------------------------------------------
|
||||
|
||||
for f=1:frames
|
||||
|
||||
% obtain nin samples of the test input signal
|
||||
|
||||
for i=1:nin
|
||||
rx_fdm(i) = fread(fin, 1, "short")/gain;
|
||||
end
|
||||
|
||||
rx_fdm_log = [rx_fdm_log rx_fdm(1:nin)];
|
||||
|
||||
% frequency offset estimation and correction
|
||||
|
||||
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
|
||||
[foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
|
||||
|
||||
if track == 0
|
||||
foff = foff_coarse;
|
||||
end
|
||||
foff_log = [ foff_log foff ];
|
||||
foff_rect = exp(j*2*pi*foff/Fs);
|
||||
|
||||
for i=1:nin
|
||||
foff_phase *= foff_rect';
|
||||
rx_fdm(i) = rx_fdm(i)*foff_phase;
|
||||
end
|
||||
|
||||
% baseband processing
|
||||
|
||||
rx_baseband = fdm_downconvert(rx_fdm, nin);
|
||||
rx_filt = rx_filter(rx_baseband, nin);
|
||||
|
||||
[rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin);
|
||||
|
||||
rx_timing_log = [rx_timing_log rx_timing];
|
||||
nin = M;
|
||||
if rx_timing > 2*M/P
|
||||
nin += M/P;
|
||||
end
|
||||
if rx_timing < 0;
|
||||
nin -= M/P;
|
||||
end
|
||||
|
||||
if strcmp(modulation,'dqpsk')
|
||||
rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
|
||||
else
|
||||
rx_symbols_log = [rx_symbols_log rx_symbols];
|
||||
endif
|
||||
[rx_bits sync f_err pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
|
||||
[sig_est noise_est] = snr_update(sig_est, noise_est, pd);
|
||||
snr_est = calc_snr(sig_est, noise_est);
|
||||
snr_est_log = [snr_est_log snr_est];
|
||||
foff -= 0.5*f_err;
|
||||
prev_rx_symbols = rx_symbols;
|
||||
sync_log = [sync_log sync];
|
||||
|
||||
% freq est state machine
|
||||
|
||||
[track fest_state] = freq_state(sync, fest_state);
|
||||
track_log = [track_log track];
|
||||
|
||||
% count bit errors if we find a test frame
|
||||
|
||||
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
|
||||
if (test_frame_sync == 1)
|
||||
total_bit_errors = total_bit_errors + bit_errors;
|
||||
total_bits = total_bits + Ntest_bits;
|
||||
bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
|
||||
else
|
||||
bit_errors_log = [bit_errors_log 0];
|
||||
end
|
||||
|
||||
% test frame sync state machine, just for more informative plots
|
||||
|
||||
next_test_frame_sync_state = test_frame_sync_state;
|
||||
if (test_frame_sync_state == 0)
|
||||
if (test_frame_sync == 1)
|
||||
next_test_frame_sync_state = 1;
|
||||
test_frame_count = 0;
|
||||
end
|
||||
end
|
||||
|
||||
if (test_frame_sync_state == 1)
|
||||
% we only expect another test_frame_sync pulse every 4 symbols
|
||||
test_frame_count++;
|
||||
if (test_frame_count == 4)
|
||||
test_frame_count = 0;
|
||||
if ((test_frame_sync == 0))
|
||||
next_test_frame_sync_state = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
test_frame_sync_state = next_test_frame_sync_state;
|
||||
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
|
||||
|
||||
end
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Print Stats
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
ber = total_bit_errors / total_bits;
|
||||
|
||||
printf("%d bits %d errors BER: %1.4f\n",total_bits, total_bit_errors, ber);
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Plots
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
xt = (1:frames)/Rs;
|
||||
secs = frames/Rs;
|
||||
|
||||
figure(1)
|
||||
clf;
|
||||
[n m] = size(rx_symbols_log);
|
||||
plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
|
||||
axis([-2 2 -2 2]);
|
||||
title('Scatter Diagram');
|
||||
|
||||
figure(2)
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(xt, rx_timing_log)
|
||||
title('timing offset (samples)');
|
||||
subplot(212)
|
||||
plot(xt, foff_log, '-;freq offset;')
|
||||
hold on;
|
||||
plot(xt, track_log*75, 'r;course-fine;');
|
||||
hold off;
|
||||
title('Freq offset (Hz)');
|
||||
grid
|
||||
|
||||
figure(3)
|
||||
clf;
|
||||
subplot(211)
|
||||
[a b] = size(rx_fdm_log);
|
||||
xt1 = (1:b)/Fs;
|
||||
plot(xt1, rx_fdm_log);
|
||||
title('Rx FDM Signal');
|
||||
subplot(212)
|
||||
spec(rx_fdm_log,8000);
|
||||
title('FDM Rx Spectrogram');
|
||||
|
||||
figure(4)
|
||||
clf;
|
||||
subplot(311)
|
||||
stem(xt, sync_log)
|
||||
axis([0 secs 0 1.5]);
|
||||
title('BPSK Sync')
|
||||
subplot(312)
|
||||
stem(xt, bit_errors_log);
|
||||
title('Bit Errors for test frames')
|
||||
subplot(313)
|
||||
plot(xt, test_frame_sync_log);
|
||||
axis([0 secs 0 1.5]);
|
||||
title('Test Frame Sync')
|
||||
|
||||
figure(5)
|
||||
clf;
|
||||
plot(xt, snr_est_log);
|
||||
title('SNR Estimates')
|
||||
|
||||
endfunction
|
|
@ -1,128 +0,0 @@
|
|||
% fdmdv_demod_c.m
|
||||
%
|
||||
% Plots Octave dump file information from C FDMDV demodulator program,
|
||||
% to give a similar set of plots to fdmdv_demod.m. Useful for off
|
||||
% line analysis of demod performance.
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
function fdmdv_demod_c(dumpfilename, bits)
|
||||
|
||||
fdmdv; % include modem code
|
||||
|
||||
frames = bits/(Nc*Nb);
|
||||
|
||||
load(dumpfilename);
|
||||
|
||||
% BER stats
|
||||
|
||||
total_bit_errors = 0;
|
||||
total_bits = 0;
|
||||
bit_errors_log = [];
|
||||
sync_log = [];
|
||||
test_frame_sync_log = [];
|
||||
test_frame_sync_state = 0;
|
||||
|
||||
% Run thru received bits to look for test pattern
|
||||
|
||||
bits_per_frame = Nc*Nb;
|
||||
|
||||
for f=1:frames
|
||||
|
||||
rx_bits = rx_bits_log_c((f-1)*bits_per_frame+1:f*bits_per_frame);
|
||||
|
||||
% count bit errors if we find a test frame
|
||||
|
||||
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
|
||||
if (test_frame_sync == 1)
|
||||
total_bit_errors = total_bit_errors + bit_errors;
|
||||
total_bits = total_bits + Ntest_bits;
|
||||
bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
|
||||
else
|
||||
bit_errors_log = [bit_errors_log 0];
|
||||
end
|
||||
|
||||
% test frame sync state machine, just for more informative plots
|
||||
|
||||
next_test_frame_sync_state = test_frame_sync_state;
|
||||
if (test_frame_sync_state == 0)
|
||||
if (test_frame_sync == 1)
|
||||
next_test_frame_sync_state = 1;
|
||||
test_frame_count = 0;
|
||||
end
|
||||
end
|
||||
|
||||
if (test_frame_sync_state == 1)
|
||||
% we only expect another test_frame_sync pulse every 4 symbols
|
||||
test_frame_count++;
|
||||
if (test_frame_count == 4)
|
||||
test_frame_count = 0;
|
||||
if ((test_frame_sync == 0))
|
||||
next_test_frame_sync_state = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
test_frame_sync_state = next_test_frame_sync_state;
|
||||
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
|
||||
end
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Plots
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
xt = (1:frames)/Rs;
|
||||
secs = frames/Rs;
|
||||
|
||||
figure(1)
|
||||
clf;
|
||||
plot(real(rx_symbols_log_c(1:Nc+1,15:frames)),imag(rx_symbols_log_c(1:Nc+1,15:frames)),'+')
|
||||
axis([-2 2 -2 2]);
|
||||
title('Scatter Diagram');
|
||||
|
||||
figure(2)
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(xt, rx_timing_log_c(1:frames))
|
||||
title('timing offset (samples)');
|
||||
subplot(212)
|
||||
plot(xt, foff_log_c(1:frames), '-;freq offset;')
|
||||
hold on;
|
||||
plot(xt, coarse_fine_log_c(1:frames)*75, 'r;course-fine;');
|
||||
hold off;
|
||||
title('Freq offset (Hz)');
|
||||
grid
|
||||
|
||||
figure(3)
|
||||
clf;
|
||||
subplot(211)
|
||||
b = M*frames;
|
||||
xt1 = (1:b)/Fs;
|
||||
plot(xt1, rx_fdm_log_c(1:b));
|
||||
title('Rx FDM Signal');
|
||||
subplot(212)
|
||||
spec(rx_fdm_log_c(1:b),8000);
|
||||
title('FDM Rx Spectrogram');
|
||||
|
||||
figure(4)
|
||||
clf;
|
||||
subplot(311)
|
||||
stem(xt, sync_bit_log_c(1:frames))
|
||||
axis([0 secs 0 1.5]);
|
||||
title('BPSK Sync')
|
||||
subplot(312)
|
||||
stem(xt, bit_errors_log);
|
||||
title('Bit Errors for test frames')
|
||||
subplot(313)
|
||||
plot(xt, test_frame_sync_log);
|
||||
axis([0 secs 0 1.5]);
|
||||
title('Test Frame Sync')
|
||||
|
||||
figure(5)
|
||||
clf;
|
||||
plot(xt, snr_est_log_c(1:frames));
|
||||
title('SNR Estimates')
|
||||
|
||||
endfunction
|
|
@ -1,32 +0,0 @@
|
|||
% fdmdv_mod.m
|
||||
%
|
||||
% Modulator function for FDMDV modem, uses test frames as input and
|
||||
% outputs a raw file of 16 bit shorts at a sample rate of 8 kHz.
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
function tx_fdm = fdmdv_mod(rawfilename, nbits)
|
||||
|
||||
fdmdv; % include modem code
|
||||
|
||||
frames = floor(nbits/(Nc*Nb))
|
||||
tx_fdm = [];
|
||||
gain = 1000; % Scale up to 16 bit shorts
|
||||
prev_tx_symbols = ones(Nc+1,1);
|
||||
|
||||
for i=1:frames
|
||||
tx_bits = get_test_bits(Nc*Nb);
|
||||
tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits,'dqpsk');
|
||||
prev_tx_symbols = tx_symbols;
|
||||
tx_baseband = tx_filter(tx_symbols);
|
||||
tx_fdm = [tx_fdm real(fdm_upconvert(tx_baseband))];
|
||||
end
|
||||
|
||||
tx_fdm *= gain;
|
||||
fout = fopen(rawfilename,"wb");
|
||||
fwrite(fout, tx_fdm, "short");
|
||||
fclose(fout);
|
||||
endfunction
|
|
@ -1,318 +0,0 @@
|
|||
% fdmdv_ut.m
|
||||
%
|
||||
% Unit Test program for FDMDV modem. Useful for general development as it has
|
||||
% both tx and rx sides, and basic AWGN channel simulation.
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
fdmdv; % load modem code
|
||||
|
||||
% Simulation Parameters --------------------------------------
|
||||
|
||||
frames = 25;
|
||||
EbNo_dB = 7.3;
|
||||
Foff_hz = 0;
|
||||
modulation = 'dqpsk';
|
||||
hpa_clip = 150;
|
||||
|
||||
% ------------------------------------------------------------
|
||||
|
||||
tx_filt = zeros(Nc,M);
|
||||
rx_symbols_log = [];
|
||||
rx_phase_log = 0;
|
||||
rx_timing_log = 0;
|
||||
tx_pwr = 0;
|
||||
noise_pwr = 0;
|
||||
rx_fdm_log = [];
|
||||
rx_baseband_log = [];
|
||||
rx_bits_offset = zeros(Nc*Nb*2);
|
||||
prev_tx_symbols = ones(Nc+1,1);
|
||||
prev_rx_symbols = ones(Nc+1,1);
|
||||
ferr = 0;
|
||||
foff = 0;
|
||||
foff_log = [];
|
||||
tx_baseband_log = [];
|
||||
tx_fdm_log = [];
|
||||
|
||||
% BER stats
|
||||
|
||||
total_bit_errors = 0;
|
||||
total_bits = 0;
|
||||
bit_errors_log = [];
|
||||
sync_log = [];
|
||||
test_frame_sync_log = [];
|
||||
test_frame_sync_state = 0;
|
||||
|
||||
% SNR estimation states
|
||||
|
||||
sig_est = zeros(Nc+1,1);
|
||||
noise_est = zeros(Nc+1,1);
|
||||
|
||||
% fixed delay simuation
|
||||
|
||||
Ndelay = M+20;
|
||||
rx_fdm_delay = zeros(Ndelay,1);
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Eb/No calculations. We need to work out Eb/No for each FDM carrier.
|
||||
% Total power is sum of power in all FDM carriers
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
C = 1; % power of each FDM carrier (energy/sample). Total Carrier power should = Nc*C = Nc
|
||||
N = 1; % total noise power (energy/sample) of noise source across entire bandwidth
|
||||
|
||||
% Eb = Carrier power * symbol time / (bits/symbol)
|
||||
% = C *(1/Rs) / 2
|
||||
Eb_dB = 10*log10(C) - 10*log10(Rs) - 10*log10(2);
|
||||
|
||||
No_dBHz = Eb_dB - EbNo_dB;
|
||||
|
||||
% Noise power = Noise spectral density * bandwidth
|
||||
% Noise power = Noise spectral density * Fs/2 for real signals
|
||||
N_dB = No_dBHz + 10*log10(Fs/2);
|
||||
Ngain_dB = N_dB - 10*log10(N);
|
||||
Ngain = 10^(Ngain_dB/20);
|
||||
|
||||
% C/No = Carrier Power/noise spectral density
|
||||
% = power per carrier*number of carriers / noise spectral density
|
||||
CNo_dB = 10*log10(C) + 10*log10(Nc) - No_dBHz;
|
||||
|
||||
% SNR in equivalent 3000 Hz SSB channel
|
||||
|
||||
B = 3000;
|
||||
SNR = CNo_dB - 10*log10(B);
|
||||
|
||||
% freq offset simulation states
|
||||
|
||||
phase_offset = 1;
|
||||
freq_offset = exp(j*2*pi*Foff_hz/Fs);
|
||||
foff_phase = 1;
|
||||
t = 0;
|
||||
foff = 0;
|
||||
fest_state = 0;
|
||||
track = 0;
|
||||
track_log = [];
|
||||
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Main loop
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
for f=1:frames
|
||||
|
||||
% -------------------
|
||||
% Modulator
|
||||
% -------------------
|
||||
|
||||
tx_bits = get_test_bits(Nc*Nb);
|
||||
tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, modulation);
|
||||
prev_tx_symbols = tx_symbols;
|
||||
tx_baseband = tx_filter(tx_symbols);
|
||||
tx_baseband_log = [tx_baseband_log tx_baseband];
|
||||
tx_fdm = fdm_upconvert(tx_baseband);
|
||||
tx_pwr = 0.9*tx_pwr + 0.1*real(tx_fdm)*real(tx_fdm)'/(M);
|
||||
|
||||
% -------------------
|
||||
% Channel simulation
|
||||
% -------------------
|
||||
|
||||
% frequency offset
|
||||
|
||||
%Foff_hz += 1/Rs;
|
||||
Foff = Foff_hz;
|
||||
for i=1:M
|
||||
% Time varying freq offset
|
||||
%Foff = Foff_hz + 100*sin(t*2*pi/(300*Fs));
|
||||
%t++;
|
||||
freq_offset = exp(j*2*pi*Foff/Fs);
|
||||
phase_offset *= freq_offset;
|
||||
tx_fdm(i) = phase_offset*tx_fdm(i);
|
||||
end
|
||||
|
||||
tx_fdm = real(tx_fdm);
|
||||
|
||||
% HPA non-linearity
|
||||
|
||||
tx_fdm(find(abs(tx_fdm) > hpa_clip)) = hpa_clip;
|
||||
tx_fdm_log = [tx_fdm_log tx_fdm];
|
||||
|
||||
rx_fdm = tx_fdm;
|
||||
|
||||
% AWGN noise
|
||||
|
||||
noise = Ngain*randn(1,M);
|
||||
noise_pwr = 0.9*noise_pwr + 0.1*noise*noise'/M;
|
||||
rx_fdm += noise;
|
||||
rx_fdm_log = [rx_fdm_log rx_fdm];
|
||||
|
||||
% Delay
|
||||
|
||||
rx_fdm_delay(1:Ndelay-M) = rx_fdm_delay(M+1:Ndelay);
|
||||
rx_fdm_delay(Ndelay-M+1:Ndelay) = rx_fdm;
|
||||
%rx_fdm_delay = rx_fdm;
|
||||
|
||||
% -------------------
|
||||
% Demodulator
|
||||
% -------------------
|
||||
|
||||
% frequency offset estimation and correction, need to call rx_est_freq_offset even in track
|
||||
% mode to keep states updated
|
||||
|
||||
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, M);
|
||||
[foff_course S1 S2] = rx_est_freq_offset(rx_fdm_delay, pilot, prev_pilot, M);
|
||||
if track == 0
|
||||
foff = foff_course;
|
||||
end
|
||||
foff_log = [ foff_log foff ];
|
||||
foff_rect = exp(j*2*pi*foff/Fs);
|
||||
|
||||
for i=1:M
|
||||
foff_phase *= foff_rect';
|
||||
rx_fdm_delay(i) = rx_fdm_delay(i)*foff_phase;
|
||||
end
|
||||
|
||||
% baseband processing
|
||||
|
||||
rx_baseband = fdm_downconvert(rx_fdm_delay(1:M), M);
|
||||
rx_baseband_log = [rx_baseband_log rx_baseband];
|
||||
rx_filt = rx_filter(rx_baseband, M);
|
||||
|
||||
[rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, M);
|
||||
rx_timing_log = [rx_timing_log rx_timing];
|
||||
|
||||
%rx_phase = rx_est_phase(rx_symbols);
|
||||
%rx_phase_log = [rx_phase_log rx_phase];
|
||||
%rx_symbols = rx_symbols*exp(j*rx_phase);
|
||||
|
||||
[rx_bits sync foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
|
||||
if strcmp(modulation,'dqpsk')
|
||||
%rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
|
||||
rx_symbols_log = [rx_symbols_log pd];
|
||||
else
|
||||
rx_symbols_log = [rx_symbols_log rx_symbols];
|
||||
endif
|
||||
foff -= 0.5*ferr;
|
||||
prev_rx_symbols = rx_symbols;
|
||||
sync_log = [sync_log sync];
|
||||
|
||||
% freq est state machine
|
||||
|
||||
[track fest_state] = freq_state(sync, fest_state);
|
||||
track_log = [track_log track];
|
||||
|
||||
% Update SNR est
|
||||
|
||||
[sig_est noise_est] = snr_update(sig_est, noise_est, pd);
|
||||
|
||||
% count bit errors if we find a test frame
|
||||
% Allow 15 frames for filter memories to fill and time est to settle
|
||||
|
||||
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
|
||||
if test_frame_sync == 1
|
||||
total_bit_errors = total_bit_errors + bit_errors;
|
||||
total_bits = total_bits + Ntest_bits;
|
||||
bit_errors_log = [bit_errors_log bit_errors];
|
||||
else
|
||||
bit_errors_log = [bit_errors_log 0];
|
||||
end
|
||||
|
||||
% test frame sync state machine, just for more informative plots
|
||||
|
||||
next_test_frame_sync_state = test_frame_sync_state;
|
||||
if (test_frame_sync_state == 0)
|
||||
if (test_frame_sync == 1)
|
||||
next_test_frame_sync_state = 1;
|
||||
test_frame_count = 0;
|
||||
end
|
||||
end
|
||||
|
||||
if (test_frame_sync_state == 1)
|
||||
% we only expect another test_frame_sync pulse every 4 symbols
|
||||
test_frame_count++;
|
||||
if (test_frame_count == 4)
|
||||
test_frame_count = 0;
|
||||
if ((test_frame_sync == 0))
|
||||
next_test_frame_sync_state = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
test_frame_sync_state = next_test_frame_sync_state;
|
||||
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
|
||||
end
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Print Stats
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
ber = total_bit_errors / total_bits;
|
||||
|
||||
% Peak to Average Power Ratio calcs from http://www.dsplog.com
|
||||
|
||||
papr = max(tx_fdm_log.*conj(tx_fdm_log)) / mean(tx_fdm_log.*conj(tx_fdm_log));
|
||||
papr_dB = 10*log10(papr);
|
||||
|
||||
% Note Eb/No set point is for Nc data carriers only, exclduing pilot.
|
||||
% This is convenient for testing BER versus Eb/No. Measured Eb/No
|
||||
% includes power of pilot. Similar for SNR, first number is SNR excluding
|
||||
% pilot pwr for Eb/No set point, 2nd value is measured SNR which will be a little
|
||||
% higher as pilot power is included.
|
||||
|
||||
printf("Eb/No (meas): %2.2f (%2.2f) dB\n", EbNo_dB, 10*log10(0.25*tx_pwr*Fs/(Rs*Nc*noise_pwr)));
|
||||
printf("bits........: %d\n", total_bits);
|
||||
printf("errors......: %d\n", total_bit_errors);
|
||||
printf("BER.........: %1.4f\n", ber);
|
||||
printf("PAPR........: %1.2f dB\n", papr_dB);
|
||||
printf("SNR...(meas): %2.2f (%2.2f) dB\n", SNR, calc_snr(sig_est, noise_est));
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
% Plots
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
figure(1)
|
||||
clf;
|
||||
[n m] = size(rx_symbols_log);
|
||||
plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
|
||||
axis([-3 3 -3 3]);
|
||||
title('Scatter Diagram');
|
||||
|
||||
figure(2)
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(rx_timing_log)
|
||||
title('timing offset (samples)');
|
||||
subplot(212)
|
||||
plot(foff_log, '-;freq offset;')
|
||||
hold on;
|
||||
plot(track_log*75, 'r;course-fine;');
|
||||
hold off;
|
||||
title('Freq offset (Hz)');
|
||||
|
||||
figure(3)
|
||||
clf;
|
||||
subplot(211)
|
||||
plot(real(tx_fdm_log));
|
||||
title('FDM Tx Signal');
|
||||
subplot(212)
|
||||
Nfft=Fs;
|
||||
S=fft(rx_fdm_log,Nfft);
|
||||
SdB=20*log10(abs(S));
|
||||
plot(SdB(1:Fs/4))
|
||||
title('FDM Rx Spectrum');
|
||||
|
||||
figure(4)
|
||||
clf;
|
||||
subplot(311)
|
||||
stem(sync_log)
|
||||
axis([0 frames 0 1.5]);
|
||||
title('BPSK Sync')
|
||||
subplot(312)
|
||||
stem(bit_errors_log);
|
||||
title('Bit Errors for test frames')
|
||||
subplot(313)
|
||||
plot(test_frame_sync_log);
|
||||
axis([0 frames 0 1.5]);
|
||||
title('Test Frame Sync')
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
% gen_rn_coeffs.m
|
||||
% David Rowe 13 april 2012
|
||||
%
|
||||
% Generate root raised cosine (Root Nyquist) filter coefficients
|
||||
% thanks http://www.dsplog.com/db-install/wp-content/uploads/2008/05/raised_cosine_filter.m
|
||||
|
||||
function coeffs = gen_rn_coeffs(alpha, T, Rs, Nsym, M)
|
||||
|
||||
Ts = 1/Rs;
|
||||
|
||||
n = -Nsym*Ts/2:T:Nsym*Ts/2;
|
||||
Nfilter = Nsym*M;
|
||||
Nfiltertiming = M+Nfilter+M;
|
||||
|
||||
sincNum = sin(pi*n/Ts); % numerator of the sinc function
|
||||
sincDen = (pi*n/Ts); % denominator of the sinc function
|
||||
sincDenZero = find(abs(sincDen) < 10^-10);
|
||||
sincOp = sincNum./sincDen;
|
||||
sincOp(sincDenZero) = 1; % sin(pix/(pix) =1 for x =0
|
||||
|
||||
cosNum = cos(alpha*pi*n/Ts);
|
||||
cosDen = (1-(2*alpha*n/Ts).^2);
|
||||
cosDenZero = find(abs(cosDen)<10^-10);
|
||||
cosOp = cosNum./cosDen;
|
||||
cosOp(cosDenZero) = pi/4;
|
||||
gt_alpha5 = sincOp.*cosOp;
|
||||
Nfft = 4096;
|
||||
GF_alpha5 = fft(gt_alpha5,Nfft)/M;
|
||||
|
||||
% sqrt causes stop band to be amplified, this hack pushes it down again
|
||||
|
||||
for i=1:Nfft
|
||||
if (abs(GF_alpha5(i)) < 0.02)
|
||||
GF_alpha5(i) *= 0.001;
|
||||
endif
|
||||
end
|
||||
GF_alpha5_root = sqrt(abs(GF_alpha5)) .* exp(j*angle(GF_alpha5));
|
||||
ifft_GF_alpha5_root = ifft(GF_alpha5_root);
|
||||
coeffs = real((ifft_GF_alpha5_root(1:Nfilter)));
|
||||
endfunction
|
|
@ -1,29 +0,0 @@
|
|||
% glottal.m
|
||||
% David Rowe 12 Sep 2009
|
||||
% Matlab script to generate the phase spectra of a glottal pulse
|
||||
|
||||
% lpc10 pulse from spandsp. When the file glottal.c was used as a part of the
|
||||
% excitation phase component in phase.c, phase_synth_zero_order(), no difference
|
||||
% in speech quality was apparent. So left out of code for now.
|
||||
|
||||
sh=12
|
||||
kexc = [ 8, -16, 26, -48, 86, -162, 294, -502, 718, -728, 184 672, -610, -672, 184, 728, 718, 502, 294, 162, 86, 48, 26, 16, 8];
|
||||
kexc = shift(kexc,sh);
|
||||
kexc = [kexc(1:sh) zeros(1,512-25) kexc(sh+1:25)];
|
||||
figure(1)
|
||||
clf
|
||||
plot(kexc)
|
||||
figure(2)
|
||||
G = fft(kexc);
|
||||
subplot(211)
|
||||
plot((1:256)*(4000/256),unwrap(angle(G(1:256))))
|
||||
subplot(212)
|
||||
plot(20*log10(abs(G)))
|
||||
|
||||
f=fopen("glottal.c","wt");
|
||||
fprintf(f,"const float glottal[]={\n");
|
||||
for m=1:255
|
||||
fprintf(f," %f,\n",angle(G(m)));
|
||||
endfor
|
||||
fprintf(f," %f};\n",angle(G(256)));
|
||||
fclose(f);
|
|
@ -1,12 +0,0 @@
|
|||
% hp_filt.m
|
||||
% David Rowe 20 Feb 2012
|
||||
|
||||
function hp_filt(in_file, out_file)
|
||||
fin = fopen(in_file,"rb");
|
||||
s = fread(fin,Inf,"short");
|
||||
b = fir1(256, 300/4000, "high");
|
||||
freqz(b);
|
||||
s_hpf = filter(b,1,s);
|
||||
fout = fopen(out_file,"wb");
|
||||
fwrite(fout, s_hpf, "short");
|
||||
endfunction
|
|
@ -1,8 +0,0 @@
|
|||
% load_raw.m
|
||||
% David Rowe 7 Oct 2009
|
||||
|
||||
function s = load_raw(fn)
|
||||
fs=fopen(fn,"rb");
|
||||
s = fread(fs,Inf,"short");
|
||||
plot(s)
|
||||
endfunction
|
|
@ -1,46 +0,0 @@
|
|||
% lpcpf.m
|
||||
% David Rowe Aug 27 2012
|
||||
% Experiments with LPC post filtering
|
||||
|
||||
function lpcpf(ak_filename, f)
|
||||
aks = load(ak_filename);
|
||||
|
||||
ak = aks(f,:);
|
||||
[tmp p] = size(ak);
|
||||
p -= 1;
|
||||
|
||||
A = freqz(1,ak, 4000);
|
||||
AdB = 20*log10(abs(A));
|
||||
|
||||
gamma = 0.5;
|
||||
gammas = gamma .^ (0:p);
|
||||
W = freqz(ak .* gammas,1, 4000);
|
||||
WdB = 20*log10(abs(W));
|
||||
|
||||
beta = 0.2;
|
||||
R = abs(freqz(ak .* gammas, ak, 4000));
|
||||
%P = (R/max(R)) .^ beta;
|
||||
P = R .^ beta;
|
||||
AP = abs(A) .* P;
|
||||
|
||||
eA = sum(abs(A) .^ 2);
|
||||
eAP = sum(AP .^ 2);
|
||||
gain = sqrt(eA/eAP)
|
||||
AP *= gain;
|
||||
|
||||
PdB = 20*log10(P);
|
||||
|
||||
APdB = 20*log10(AP);
|
||||
10*log10(sum(AP .^ 2))/10*log10(sum(abs(A) .^ 2))
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(AdB);
|
||||
hold on;
|
||||
plot(WdB,'g');
|
||||
plot(PdB,'r');
|
||||
plot(APdB,'b.');
|
||||
hold off;
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
% lsp_pdf.m
|
||||
% David Rowe 2 Oct 2009
|
||||
% Plots histograms (PDF estimates) of LSP training data
|
||||
|
||||
function lsp_pdf(lsp)
|
||||
[r,c] = size(lsp);
|
||||
|
||||
% LSPs
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
[x,y] = hist(lsp(:,1),100);
|
||||
plot(y*4000/pi,x,"+;1;");
|
||||
hold on;
|
||||
for i=2:5
|
||||
[x,y] = hist(lsp(:,i),100);
|
||||
legend = sprintf("+%d;%d;",i,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
endfor
|
||||
for i=6:c
|
||||
[x,y] = hist(lsp(:,i),100);
|
||||
legend = sprintf("+%d;%d;",i-5,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
endfor
|
||||
hold off;
|
||||
grid;
|
||||
|
||||
% LSP differences
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
[x,y] = hist(lsp(:,1),100);
|
||||
plot(y*4000/pi,x,"1;1;");
|
||||
hold on;
|
||||
for i=2:5
|
||||
[x,y] = hist(lsp(:,i) - lsp(:,i-1),100);
|
||||
legend = sprintf("%d;%d;",i,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
endfor
|
||||
hold off;
|
||||
grid;
|
||||
|
||||
subplot(212)
|
||||
[x,y] = hist(lsp(:,6)-lsp(:,5),100);
|
||||
plot(y*4000/pi,x,"1;6;");
|
||||
hold on;
|
||||
for i=7:c
|
||||
[x,y] = hist(lsp(:,i) - lsp(:,i-1),100);
|
||||
legend = sprintf("%d;%d;",i-5,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
endfor
|
||||
hold off;
|
||||
grid;
|
||||
|
||||
% LSP differences delta from last frame
|
||||
|
||||
lspd(:,1) = lsp(:,1);
|
||||
lspd(:,2:10) = lsp(:,2:10) - lsp(:,1:9);
|
||||
|
||||
[m,n] = size(lspd);
|
||||
lspdd = lspd(5:m,:) - lspd(1:m-4,:);
|
||||
|
||||
figure(3);
|
||||
clf;
|
||||
subplot(211)
|
||||
for i=1:5
|
||||
[x,y] = hist(lspdd(:,i),100);
|
||||
legend = sprintf("%d;%d;",i,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
hold on;
|
||||
endfor
|
||||
hold off;
|
||||
grid;
|
||||
axis([-200 200 0 35000]);
|
||||
|
||||
subplot(212)
|
||||
for i=6:10
|
||||
[x,y] = hist(lspdd(:,i),100);
|
||||
legend = sprintf("%d;%d;",i-5,i);
|
||||
plot(y*4000/pi,x,legend);
|
||||
hold on;
|
||||
endfor
|
||||
hold off;
|
||||
grid;
|
||||
axis([-200 200 0 16000]);
|
||||
|
||||
figure(4);
|
||||
clf;
|
||||
plot((4000/pi)*(lsp(2:r,3)-lsp(1:r-1,3)))
|
||||
endfunction
|
|
@ -1,40 +0,0 @@
|
|||
% lspwarp.m
|
||||
% David Rowe Sep 2012
|
||||
%
|
||||
% Experimenting with non-linear LSP frequency axis for LSP quantisation
|
||||
% Plots a scaled mel axis.
|
||||
|
||||
1;
|
||||
|
||||
function mel = freq2mel(f)
|
||||
mel = 70*log10(1 + f/700);
|
||||
endfunction
|
||||
|
||||
function freq = mel2freq(m)
|
||||
freq = 700*(10 ^ (m/70) - 1);
|
||||
endfunction
|
||||
|
||||
x = []; y = [];
|
||||
|
||||
for freq = 100:25:4000
|
||||
mel = freq2mel(freq);
|
||||
x = [x freq];
|
||||
y = [y mel];
|
||||
end
|
||||
|
||||
plot(x,y)
|
||||
grid
|
||||
|
||||
mel_start = floor(freq2mel(100));
|
||||
mel_end = floor(freq2mel(4000));
|
||||
|
||||
x = []; y = [];
|
||||
for mel=mel_start:mel_end
|
||||
freq = mel2freq(mel);
|
||||
x = [x freq];
|
||||
y = [y mel];
|
||||
end
|
||||
|
||||
hold on;
|
||||
plot(x,y, '+')
|
||||
hold off;
|
|
@ -1,56 +0,0 @@
|
|||
% phase.m
|
||||
% David Rowe August 2009
|
||||
% experiments with phase for sinusoidal codecs
|
||||
|
||||
function phase(samname, F0, png)
|
||||
Wo=2*pi*F0/8000;
|
||||
P=2*pi/Wo;
|
||||
L = floor(pi/Wo);
|
||||
Nsam = 16000;
|
||||
N = 80;
|
||||
F = Nsam/N;
|
||||
A = 10000/L;
|
||||
phi = zeros(1,L);
|
||||
s = zeros(1,Nsam);
|
||||
|
||||
for m=floor(L/2):L
|
||||
phi_off(m) = -m*Wo*8;
|
||||
end
|
||||
|
||||
for f=1:F
|
||||
phi(1) = phi(1) + Wo*N;
|
||||
phi(1) = mod(phi(1),2*pi);
|
||||
|
||||
for m=1:L
|
||||
phi(m) = m*phi(1);
|
||||
end
|
||||
|
||||
x = zeros(1,N);
|
||||
for m=1:L
|
||||
x = x + A*cos(m*Wo*(0:(N-1)) + phi(m));
|
||||
endfor
|
||||
s((f-1)*N+1:f*N) = x;
|
||||
endfor
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(s(1:250));
|
||||
|
||||
fs=fopen(samname,"wb");
|
||||
fwrite(fs,s,"short");
|
||||
fclose(fs);
|
||||
|
||||
if (nargin == 3)
|
||||
% small image to fit blog
|
||||
|
||||
__gnuplot_set__ terminal png size 450,300
|
||||
ss = sprintf("__gnuplot_set__ output \"%s.png\"", samname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% for some reason I need this to stop large plot getting wiped
|
||||
__gnuplot_set__ output "/dev/null"
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
% phase2.m
|
||||
% David Rowe Sep 2009
|
||||
% experiments with phase for sinusoidal codecs, looking at phase
|
||||
% of excitation with real Am samples from hts1
|
||||
|
||||
function phase2(samname, png)
|
||||
N = 16000;
|
||||
|
||||
f=43;
|
||||
model = load("../src/hts1a_phase_model.txt");
|
||||
phase = load("../src/hts1a_phase_phase.txt");
|
||||
Wo = model(f,1);
|
||||
P=2*pi/Wo;
|
||||
L = model(f,2);
|
||||
A = model(f,3:(L+2));
|
||||
phi = phase(f,1:L);
|
||||
phi = zeros(1,L);
|
||||
phi(3) = -pi/2;
|
||||
phi(4) = -pi/4;
|
||||
phi(5) = pi/2;
|
||||
|
||||
s = zeros(1,N);
|
||||
|
||||
for m=3:5
|
||||
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m));
|
||||
s = s + s_m;
|
||||
endfor
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(s(1:250));
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(A),'+');
|
||||
subplot(212)
|
||||
plot((1:L)*Wo*4000/pi, phi,'+');
|
||||
|
||||
fs=fopen(samname,"wb");
|
||||
fwrite(fs,s,"short");
|
||||
fclose(fs);
|
||||
|
||||
if (nargin == 2)
|
||||
% small image to fit blog
|
||||
|
||||
__gnuplot_set__ terminal png size 450,300
|
||||
ss = sprintf("__gnuplot_set__ output \"%s.png\"", samname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% for some reason I need this to stop large plot getting wiped
|
||||
__gnuplot_set__ output "/dev/null"
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
% phasesecord.m
|
||||
% David Rowe Aug 2012
|
||||
% Used to experiment with aproximations of phase of 2nd order systems
|
||||
|
||||
function phasesecord(w,beta)
|
||||
|
||||
a = [1 -2*cos(w)*beta beta*beta];
|
||||
b = 1;
|
||||
|
||||
[h w1] = freqz(b,a);
|
||||
|
||||
figure(1)
|
||||
subplot(211)
|
||||
plot(abs(h))
|
||||
subplot(212)
|
||||
plot(angle(h))
|
||||
|
||||
% for beta close to 1, we approximate 3 dB points as 1-beta above
|
||||
% and below the resonance freq. Note this fails if w=0 as there is a
|
||||
% double pole. Lets sample the freq response at the 3dB points and
|
||||
% w:
|
||||
|
||||
ws = [w-(1-beta) w w+(1-beta)];
|
||||
[h w1] = freqz(b,a,ws);
|
||||
|
||||
% gain as a fraction of max, should be 3dB. Within 1.3 dB or for w > pi/8,
|
||||
% gets innacurate near w=0 due to 2nd pole
|
||||
|
||||
printf("mag measured...:"); printf("% 4.3f ", abs(h)/max(abs(h)));
|
||||
|
||||
% measured angle, 45 deg from angle at w
|
||||
|
||||
printf("\nangle measured.: "); printf("% 5.3f ", angle(h));
|
||||
|
||||
% Our estimate of angle, (pi+w) is phase at resonance, at lower 3dB
|
||||
% phase is pi/4 ahead, at upper 3B pi/4 behind. -pi/2 is contribution of
|
||||
% other pole at at -w to phase
|
||||
|
||||
ph_lower = (pi+w) + pi/4 - pi/2;
|
||||
ph_res =(pi+w) - pi/2;
|
||||
ph_upper = (pi+w) - pi/4 - pi/2;
|
||||
ph_ests = [ph_lower ph_res ph_upper];
|
||||
ph_ests = ph_ests - 2*pi*(floor(ph_ests/(2*pi)) + 0.5);
|
||||
printf("\nangle estimated:"); printf("% 5.3f ", ph_ests);
|
||||
printf("\n");
|
||||
endfunction
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
% pitch_test.m
|
||||
% David Rowe Sep 2009
|
||||
% Constructs a sequence to test the pitch estimator
|
||||
|
||||
function pitch_test(samname)
|
||||
M=320;
|
||||
F=200;
|
||||
|
||||
fs=fopen(samname,"wb");
|
||||
|
||||
f0 = 100;
|
||||
for f=1:200
|
||||
Wo=2*pi*f0/8000;
|
||||
P=2*pi/Wo;
|
||||
L = floor(pi/Wo);
|
||||
A = 10000/L;
|
||||
phi = zeros(1,L);
|
||||
s = zeros(1,M);
|
||||
|
||||
for m=1:L
|
||||
s = s + A*cos(m*Wo*(0:(M-1)) + phi(m));
|
||||
endfor
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(s);
|
||||
|
||||
fwrite(fs,s,"short");
|
||||
|
||||
f0 = f0 + 5;
|
||||
if (f0 > 400)
|
||||
f0 = 100;
|
||||
endif
|
||||
endfor
|
||||
|
||||
fclose(fs);
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plots a raw speech sample file, you can optionally specify the start and end
|
||||
% samples and create a large and small PNGs
|
||||
|
||||
function pl(samname1, start_sam, end_sam, pngname)
|
||||
|
||||
fs=fopen(samname1,"rb");
|
||||
s=fread(fs,Inf,"short");
|
||||
|
||||
st = 1;
|
||||
en = length(s);
|
||||
if (nargin >= 2)
|
||||
st = start_sam;
|
||||
endif
|
||||
if (nargin >= 3)
|
||||
en = end_sam;
|
||||
endif
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
plot(s(st:en));
|
||||
axis([1 en-st 1.1*min(s) 1.1*max(s)]);
|
||||
|
||||
if (nargin == 4)
|
||||
|
||||
% small image
|
||||
|
||||
__gnuplot_set__ terminal png size 420,300
|
||||
ss = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% larger image
|
||||
|
||||
__gnuplot_set__ terminal png size 800,600
|
||||
ss = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
endif
|
||||
|
||||
endfunction
|
|
@ -1,50 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
|
||||
function pl2(samname1, samname2, start_sam, end_sam, pngname)
|
||||
|
||||
fs1=fopen(samname1,"rb");
|
||||
s1=fread(fs1,Inf,"short");
|
||||
fs2=fopen(samname2,"rb");
|
||||
s2=fread(fs2,Inf,"short");
|
||||
|
||||
st = 1;
|
||||
en = length(s1);
|
||||
if (nargin >= 3)
|
||||
st = start_sam;
|
||||
endif
|
||||
if (nargin >= 4)
|
||||
en = end_sam;
|
||||
endif
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211);
|
||||
l1 = strcat("r;",samname1,";");
|
||||
plot(s1(st:en), l1);
|
||||
axis([1 en-st min(s1(st:en)) max(s1(st:en))]);
|
||||
subplot(212);
|
||||
l2 = strcat("r;",samname2,";");
|
||||
plot(s2(st:en),l2);
|
||||
axis([1 en-st min(s1(st:en)) max(s1(st:en))]);
|
||||
|
||||
if (nargin == 5)
|
||||
|
||||
% small image
|
||||
|
||||
__gnuplot_set__ terminal png size 420,300
|
||||
s = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
|
||||
eval(s)
|
||||
replot;
|
||||
|
||||
% larger image
|
||||
|
||||
__gnuplot_set__ terminal png size 800,600
|
||||
s = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
|
||||
eval(s)
|
||||
replot;
|
||||
|
||||
endif
|
||||
|
||||
endfunction
|
|
@ -1,197 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot ampltiude modelling information from dump files.
|
||||
|
||||
function plamp(samname, f, samname2)
|
||||
|
||||
% switch some stuff off to unclutter display
|
||||
|
||||
plot_lsp = 0;
|
||||
plot_snr = 0;
|
||||
plot_vsnr = 0;
|
||||
plot_sw = 0;
|
||||
plot_pw = 0;
|
||||
|
||||
sn_name = strcat(samname,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
sw_name = strcat(samname,"_sw.txt");
|
||||
Sw = load(sw_name);
|
||||
|
||||
sw__name = strcat(samname,"_sw_.txt");
|
||||
if (file_in_path(".",sw__name))
|
||||
Sw_ = load(sw__name);
|
||||
endif
|
||||
|
||||
ew_name = strcat(samname,"_ew.txt");
|
||||
if (file_in_path(".",ew_name))
|
||||
Ew = load(ew_name);
|
||||
endif
|
||||
|
||||
rk_name = strcat(samname,"_rk.txt");
|
||||
if (file_in_path(".",rk_name))
|
||||
Rk = load(rk_name);
|
||||
endif
|
||||
|
||||
model_name = strcat(samname,"_model.txt");
|
||||
model = load(model_name);
|
||||
|
||||
modelq_name = strcat(samname,"_qmodel.txt");
|
||||
if (file_in_path(".",modelq_name))
|
||||
modelq = load(modelq_name);
|
||||
endif
|
||||
|
||||
pw_name = strcat(samname,"_pw.txt");
|
||||
if (file_in_path(".",pw_name))
|
||||
Pw = load(pw_name);
|
||||
endif
|
||||
|
||||
lsp_name = strcat(samname,"_lsp.txt");
|
||||
if (file_in_path(".",lsp_name))
|
||||
lsp = load(lsp_name);
|
||||
endif
|
||||
|
||||
phase_name = strcat(samname,"_phase.txt");
|
||||
if (file_in_path(".",phase_name))
|
||||
phase = load(phase_name);
|
||||
endif
|
||||
|
||||
phase_name_ = strcat(samname,"_phase_.txt");
|
||||
if (file_in_path(".",phase_name_))
|
||||
phase_ = load(phase_name_);
|
||||
endif
|
||||
|
||||
snr_name = strcat(samname,"_snr.txt");
|
||||
if (file_in_path(".",snr_name))
|
||||
snr = load(snr_name);
|
||||
endif
|
||||
|
||||
% optional second file, for exploring post filter
|
||||
|
||||
model2q_name = " ";
|
||||
if nargin == 3
|
||||
model2q_name = strcat(samname2,"_qmodel.txt");
|
||||
if file_in_path(".",modelq_name)
|
||||
model2q = load(model2q_name);
|
||||
end
|
||||
end
|
||||
|
||||
Ew_on = 1;
|
||||
k = ' ';
|
||||
do
|
||||
figure(1);
|
||||
clf;
|
||||
% s = [ Sn(2*(f-2)-1,:) Sn(2*(f-2),:) ];
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
size(s);
|
||||
plot(s);
|
||||
axis([1 length(s) -20000 20000]);
|
||||
|
||||
figure(2);
|
||||
Wo = model(f,1);
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Am),";Am;r");
|
||||
axis([1 4000 -10 80]);
|
||||
hold on;
|
||||
if plot_sw
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
end
|
||||
|
||||
if (file_in_path(".",modelq_name))
|
||||
Amq = modelq(f,3:(L+2));
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Amq),";Amq;g" );
|
||||
if (file_in_path(".",pw_name) && plot_pw)
|
||||
plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;c");
|
||||
endif
|
||||
signal = Am * Am';
|
||||
noise = (Am-Amq) * (Am-Amq)';
|
||||
snr1 = 10*log10(signal/noise);
|
||||
Am_err_label = sprintf(";Am error SNR %4.2f dB;m",snr1);
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Amq) - 20*log10(Am), Am_err_label);
|
||||
endif
|
||||
|
||||
if file_in_path(".",model2q_name)
|
||||
Amq2 = model2q(f,3:(L+2));
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Amq2),";Amq2;m" );
|
||||
end
|
||||
|
||||
if (file_in_path(".",snr_name) && plot_vsnr)
|
||||
snr_label = sprintf(";Voicing SNR %4.2f dB;",snr(f));
|
||||
plot(1,1,snr_label);
|
||||
endif
|
||||
|
||||
% phase model - determine SNR and error spectrum for phase model 1
|
||||
|
||||
if (file_in_path(".",phase_name_))
|
||||
orig = Am.*exp(j*phase(f,1:L));
|
||||
synth = Am.*exp(j*phase_(f,1:L));
|
||||
signal = orig * orig';
|
||||
noise = (orig-synth) * (orig-synth)';
|
||||
snr_phase = 10*log10(signal/noise);
|
||||
|
||||
%phase_err_label = sprintf(";phase_err SNR %4.2f dB;",snr_phase);
|
||||
%plot((1:L)*Wo*4000/pi, 20*log10(orig-synth), phase_err_label);
|
||||
endif
|
||||
|
||||
if (file_in_path(".",lsp_name) && plot_lsp)
|
||||
for l=1:10
|
||||
plot([lsp(f,l)*4000/pi lsp(f,l)*4000/pi], [60 80], 'r');
|
||||
endfor
|
||||
endif
|
||||
|
||||
hold off;
|
||||
|
||||
%if (file_in_path(".",phase_name))
|
||||
%figure(3);
|
||||
%plot((1:L)*Wo*4000/pi, phase(f,1:L), ";phase;");
|
||||
%axis;
|
||||
%if (file_in_path(".",phase_name_))
|
||||
%hold on;
|
||||
%plot((1:L)*Wo*4000/pi, phase_(f,1:L), ";phase_;");
|
||||
%hold off;
|
||||
%endif
|
||||
%figure(2);
|
||||
%endif
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back p-png q-quit e-toggle Ew", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
if (k == 'e')
|
||||
if (Ew_on == 1)
|
||||
Ew_on = 0;
|
||||
else
|
||||
Ew_on = 1;
|
||||
endif
|
||||
endif
|
||||
|
||||
% optional print to PNG
|
||||
|
||||
if (k == 'p')
|
||||
figure(1);
|
||||
pngname = sprintf("%s_%d_sn.png",samname,f);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_%d_sn_large.png",samname,f);
|
||||
print(pngname, '-dpng', "-S800,600")
|
||||
|
||||
figure(2);
|
||||
pngname = sprintf("%s_%d_sw.png",samname,f);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_%d_sw_large.png",samname,f);
|
||||
print(pngname, '-dpng', "-S1200,800")
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,11 +0,0 @@
|
|||
load ../unittest/tinterp_prev.txt;
|
||||
load ../unittest/tinterp_interp.txt;
|
||||
load ../unittest/tinterp_next.txt;
|
||||
|
||||
clf;
|
||||
plot(tinterp_prev(:,1), 20.0*log10(tinterp_prev(:,2)),";prev;")
|
||||
hold on;
|
||||
plot(tinterp_interp(:,1), 20.0*log10(tinterp_interp(:,2)),'g+-;interp;')
|
||||
plot(tinterp_next(:,1), 20.0*log10(tinterp_next(:,2)),'ro-;next;')
|
||||
hold off;
|
||||
axis([0 pi 0 80])
|
|
@ -1,150 +0,0 @@
|
|||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot amplitude modelling information from dump files to test and develop
|
||||
% LPC post filter.
|
||||
|
||||
function pllpcpf(samname, f)
|
||||
|
||||
% switch some stuff off to unclutter display
|
||||
|
||||
plot_Am = 0;
|
||||
plot_Amq = 0;
|
||||
plot_err = 0;
|
||||
plot_lsp = 0;
|
||||
plot_snr = 0;
|
||||
plot_vsnr = 0;
|
||||
plot_sw = 0;
|
||||
plot_pw = 1;
|
||||
plot_pwb = 1;
|
||||
plot_rw = 1;
|
||||
|
||||
sn_name = strcat(samname,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
sw_name = strcat(samname,"_sw.txt");
|
||||
Sw = load(sw_name);
|
||||
|
||||
sw__name = strcat(samname,"_sw_.txt");
|
||||
if (file_in_path(".",sw__name))
|
||||
Sw_ = load(sw__name);
|
||||
endif
|
||||
|
||||
model_name = strcat(samname,"_model.txt");
|
||||
model = load(model_name);
|
||||
|
||||
modelq_name = strcat(samname,"_qmodel.txt");
|
||||
if (file_in_path(".",modelq_name))
|
||||
modelq = load(modelq_name);
|
||||
endif
|
||||
|
||||
% Pw (LPC synth filter spectrum) before post filter
|
||||
|
||||
pwb_name = strcat(samname,"_pwb.txt");
|
||||
if (file_in_path(".",pwb_name))
|
||||
Pwb = load(pwb_name);
|
||||
endif
|
||||
|
||||
% Rw (Post filter spectrum)
|
||||
|
||||
rw_name = strcat(samname,"_rw.txt");
|
||||
if (file_in_path(".",rw_name))
|
||||
Rw = load(rw_name);
|
||||
endif
|
||||
|
||||
% Pw (LPC synth filter spectrum) after post filter
|
||||
|
||||
pw_name = strcat(samname,"_pw.txt");
|
||||
if (file_in_path(".",pw_name))
|
||||
Pw = load(pw_name);
|
||||
endif
|
||||
|
||||
|
||||
Ew_on = 1;
|
||||
k = ' ';
|
||||
do
|
||||
figure(1);
|
||||
clf;
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
size(s);
|
||||
plot(s);
|
||||
axis([1 length(s) -20000 20000]);
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
Wo = model(f,1);
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
if plot_Am
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Am),";Am;r");
|
||||
end
|
||||
axis([1 4000 -10 80]);
|
||||
hold on;
|
||||
if plot_sw
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
end
|
||||
|
||||
if (file_in_path(".",modelq_name))
|
||||
|
||||
Amq = modelq(f,3:(L+2));
|
||||
if plot_Amq
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Amq),";Amq;g" );
|
||||
end
|
||||
|
||||
if (file_in_path(".",pwb_name) && plot_pwb)
|
||||
plot((0:255)*4000/256, 10*log10(Pwb(f,:)),";Pwb;r");
|
||||
endif
|
||||
|
||||
if (file_in_path(".",rw_name) && plot_rw)
|
||||
plot((0:255)*4000/256, 10*log10(Rw(f,:)),";Rw;b");
|
||||
endif
|
||||
|
||||
if (file_in_path(".",pw_name) && plot_pw)
|
||||
plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;g.");
|
||||
endif
|
||||
|
||||
signal = Am * Am';
|
||||
noise = (Am-Amq) * (Am-Amq)';
|
||||
snr1 = 10*log10(signal/noise);
|
||||
Am_err_label = sprintf(";Am error SNR %4.2f dB;m",snr1);
|
||||
if plot_err
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Amq) - 20*log10(Am), Am_err_label);
|
||||
end
|
||||
endif
|
||||
|
||||
|
||||
hold off;
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back p-png q-quit", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
|
||||
% optional print to PNG
|
||||
|
||||
if (k == 'p')
|
||||
figure(1);
|
||||
pngname = sprintf("%s_%d_sn.png",samname,f);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_%d_sn_large.png",samname,f);
|
||||
print(pngname, '-dpng', "-S800,600")
|
||||
|
||||
figure(2);
|
||||
pngname = sprintf("%s_%d_sw.png",samname,f);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_%d_sw_large.png",samname,f);
|
||||
print(pngname, '-dpng', "-S1200,800")
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,46 +0,0 @@
|
|||
% Copyright David Rowe 2010
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plots a bunch of information related to LSP quantisation:
|
||||
% - speech file
|
||||
% - LSPs before and after quantisation
|
||||
% - SNR for each frame
|
||||
%
|
||||
% Note: there is a 160 sample (two frame delay) from the when a sample
|
||||
% enters the input buffer until it is at the centre of the analysis window
|
||||
|
||||
function pllsp(rawfile,
|
||||
dumpfile_prefix_lpc_only,
|
||||
dumpfile_prefix_lsp,
|
||||
start_f, end_f)
|
||||
|
||||
fs=fopen(rawfile,"rb");
|
||||
s=fread(fs,Inf,"short");
|
||||
|
||||
lpc_snr_name = strcat(dumpfile_prefix_lpc_only,"_lpc_snr.txt");
|
||||
lpc10_snr = load(lpc_snr_name);
|
||||
lpc_snr_name = strcat(dumpfile_prefix_lsp,"_lpc_snr.txt");
|
||||
lsp_snr = load(lpc_snr_name);
|
||||
|
||||
lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
|
||||
lsps = load(lsp_name);
|
||||
[m,n]=size(lsps);
|
||||
lsp = lsps(1:2:m,:);
|
||||
lsp_ = lsps(2:2:m,:);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211);
|
||||
sp = s((start_f-2)*80:(end_f-2)*80);
|
||||
plot(sp);
|
||||
|
||||
subplot(212);
|
||||
plot(lpc10_snr((start_f+1):end_f)-lsp_snr((start_f+1):end_f));
|
||||
|
||||
figure(2);
|
||||
plot((4000/pi)*lsp((start_f+1):end_f,:));
|
||||
hold on;
|
||||
plot((4000/pi)*lsp_((start_f+1):end_f,:),'+-');
|
||||
hold off;
|
||||
endfunction
|
|
@ -1,27 +0,0 @@
|
|||
% pllspdt.m
|
||||
% Copyright David Rowe 2010
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Test script to plot differences in LSps between frames
|
||||
|
||||
function pllspdt(rawfile,dumpfile_prefix_lsp,lspn, start_f, end_f)
|
||||
|
||||
fs=fopen(rawfile,"rb");
|
||||
s=fread(fs,Inf,"short");
|
||||
|
||||
lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
|
||||
lsps = load(lsp_name);
|
||||
[m,n]=size(lsps);
|
||||
lsp = lsps(1:2:m,:);
|
||||
lsp_ = lsps(2:2:m,:);
|
||||
lspdt = lsp(2:m/2,:) - lsp(1:m/2-1,:);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
sp = s((start_f-2)*80:(end_f-2)*80);
|
||||
plot(sp);
|
||||
|
||||
figure(2);
|
||||
plot((4000/pi)*lspdt((start_f+1):end_f,lspn));
|
||||
endfunction
|
|
@ -1,134 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot NLP states from dump files.
|
||||
|
||||
function plnlp(samname, f)
|
||||
|
||||
sn_name = strcat(samname,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
sw_name = strcat(samname,"_sw.txt");
|
||||
Sw = load(sw_name);
|
||||
|
||||
fw_name = strcat(samname,"_fw.txt");
|
||||
if (file_in_path(".",fw_name))
|
||||
fw = load(fw_name);
|
||||
endif
|
||||
|
||||
e_name = strcat(samname,"_e.txt");
|
||||
if (file_in_path(".",e_name))
|
||||
e = load(e_name);
|
||||
endif
|
||||
|
||||
p_name = strcat(samname,".p");
|
||||
if (file_in_path(".",p_name))
|
||||
p = load(p_name);
|
||||
endif
|
||||
|
||||
sq_name = strcat(samname,"_sq.txt");
|
||||
if (file_in_path(".",sq_name))
|
||||
sq = load(sq_name);
|
||||
endif
|
||||
|
||||
dec_name = strcat(samname,"_dec.txt");
|
||||
if (file_in_path(".",dec_name))
|
||||
dec = load(dec_name);
|
||||
endif
|
||||
|
||||
do
|
||||
figure(1);
|
||||
clf;
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
plot(s, ";Sn;");
|
||||
grid
|
||||
axis([1 length(s) -20000 20000]);
|
||||
|
||||
figure(2);
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
grid
|
||||
axis([1 4000 -10 80]);
|
||||
hold on;
|
||||
|
||||
f0 = 8000/p(f);
|
||||
Wo = 2*pi/p(f);
|
||||
L = floor(pi/Wo);
|
||||
f0_label = sprintf("b;P=%3.1f F0=%3.0f;",p(f),f0);
|
||||
for m=1:L-1
|
||||
plot([ m*Wo*4000/pi m*Wo*4000/pi], [10 60], 'b');
|
||||
endfor
|
||||
plot([ L*Wo*4000/pi L*Wo*4000/pi], [10 60], f0_label);
|
||||
|
||||
hold off;
|
||||
|
||||
if (file_in_path(".",fw_name))
|
||||
figure(3);
|
||||
if (file_in_path(".",e_name))
|
||||
subplot(211);
|
||||
endif
|
||||
plot((0:255)*800/256, fw(f,:)/max(fw(f,:)), ";Fw;");
|
||||
axis([1 400 0 1]);
|
||||
if (file_in_path(".",e_name))
|
||||
subplot(212);
|
||||
e_concat = [ e(2*f-1,:) e(2*f,:) ];
|
||||
plot(e_concat(1:400)/max(e_concat(1:400)), "+;MBE E(f);");
|
||||
axis([1 400 0 1]);
|
||||
endif
|
||||
endif
|
||||
|
||||
if (file_in_path(".",sq_name))
|
||||
figure(4);
|
||||
sq_concat = [ sq(2*f-1,:) sq(2*f,:) ];
|
||||
axis
|
||||
plot(sq_concat, ";sq;");
|
||||
endif
|
||||
|
||||
if (file_in_path(".",dec_name))
|
||||
figure(5);
|
||||
plot(dec(f,:), ";dec;");
|
||||
endif
|
||||
|
||||
figure(2);
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
|
||||
% optional print to PNG
|
||||
|
||||
if (k == 'p')
|
||||
|
||||
pngname = sprintf("%s_%d",samname,f);
|
||||
|
||||
% small image
|
||||
|
||||
__gnuplot_set__ terminal png size 420,300
|
||||
ss = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% larger image
|
||||
|
||||
__gnuplot_set__ terminal png size 800,600
|
||||
ss = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% for some reason I need this to stop large plot getting wiped
|
||||
__gnuplot_set__ output "/dev/null"
|
||||
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,198 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot phase modelling information from dump files.
|
||||
|
||||
function plphase(samname, f)
|
||||
|
||||
sn_name = strcat(samname,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
sw_name = strcat(samname,"_sw.txt");
|
||||
Sw = load(sw_name);
|
||||
|
||||
model_name = strcat(samname,"_model.txt");
|
||||
model = load(model_name);
|
||||
|
||||
sw__name = strcat(samname,"_sw_.txt");
|
||||
if (file_in_path(".",sw__name))
|
||||
Sw_ = load(sw__name);
|
||||
endif
|
||||
|
||||
pw_name = strcat(samname,"_pw.txt");
|
||||
if (file_in_path(".",pw_name))
|
||||
Pw = load(pw_name);
|
||||
endif
|
||||
|
||||
ak_name = strcat(samname,"_ak.txt");
|
||||
if (file_in_path(".",ak_name))
|
||||
ak = load(ak_name);
|
||||
endif
|
||||
|
||||
phase_name = strcat(samname,"_phase.txt");
|
||||
if (file_in_path(".",phase_name))
|
||||
phase = load(phase_name);
|
||||
endif
|
||||
|
||||
phase_name_ = strcat(samname,"_phase_.txt");
|
||||
if (file_in_path(".",phase_name_))
|
||||
phase_ = load(phase_name_);
|
||||
endif
|
||||
|
||||
snr_name = strcat(samname,"_snr.txt");
|
||||
if (file_in_path(".",snr_name))
|
||||
snr = load(snr_name);
|
||||
endif
|
||||
|
||||
sn_name_ = strcat(samname,".raw");
|
||||
if (file_in_path(".",sn_name_))
|
||||
fs_ = fopen(sn_name_,"rb");
|
||||
sn_ = fread(fs_,Inf,"short");
|
||||
endif
|
||||
|
||||
k = ' ';
|
||||
do
|
||||
figure(1);
|
||||
clf;
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
plot(s);
|
||||
grid;
|
||||
axis([1 length(s) -20000 20000]);
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d_sn",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
|
||||
figure(2);
|
||||
Wo = model(f,1);
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(Am),"r;Am;");
|
||||
axis([1 4000 -10 80]);
|
||||
hold on;
|
||||
plot((0:255)*4000/256, Sw(f,:),";Sw;");
|
||||
grid;
|
||||
|
||||
if (file_in_path(".",sw__name))
|
||||
plot((0:255)*4000/256, Sw_(f,:),"g;Sw_;");
|
||||
endif
|
||||
|
||||
if (file_in_path(".",pw_name))
|
||||
plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;");
|
||||
endif
|
||||
|
||||
if (file_in_path(".",snr_name))
|
||||
snr_label = sprintf(";phase SNR %4.2f dB;",snr(f));
|
||||
plot(1,1,snr_label);
|
||||
endif
|
||||
|
||||
% phase model - determine SNR and error spectrum for phase model 1
|
||||
|
||||
if (file_in_path(".",phase_name_))
|
||||
orig = Am.*exp(j*phase(f,1:L));
|
||||
synth = Am.*exp(j*phase_(f,1:L));
|
||||
signal = orig * orig';
|
||||
noise = (orig-synth) * (orig-synth)';
|
||||
snr_phase = 10*log10(signal/noise);
|
||||
|
||||
phase_err_label = sprintf("g;phase_err SNR %4.2f dB;",snr_phase);
|
||||
plot((1:L)*Wo*4000/pi, 20*log10(orig-synth), phase_err_label);
|
||||
endif
|
||||
|
||||
hold off;
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d_sw",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
|
||||
if (file_in_path(".",phase_name))
|
||||
figure(3);
|
||||
plot((1:L)*Wo*4000/pi, phase(f,1:L)*180/pi, "-o;phase;");
|
||||
axis;
|
||||
if (file_in_path(".", phase_name_))
|
||||
hold on;
|
||||
plot((1:L)*Wo*4000/pi, phase_(f,1:L)*180/pi, "g;phase after;");
|
||||
grid
|
||||
hold off;
|
||||
endif
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d_phase",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
endif
|
||||
|
||||
% synthesised speech
|
||||
|
||||
if (file_in_path(".",sn_name_))
|
||||
figure(4);
|
||||
s_ = sn_((f-3)*80+1:(f+1)*80);
|
||||
plot(s_);
|
||||
axis([1 length(s_) -20000 20000]);
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d_sn_",samname,f)
|
||||
png(pngname);
|
||||
endif
|
||||
endif
|
||||
|
||||
if (file_in_path(".",ak_name))
|
||||
figure(5);
|
||||
axis;
|
||||
akw = ak(f,:);
|
||||
weight = 1.0 .^ (0:length(akw)-1);
|
||||
akw = akw .* weight;
|
||||
H = 1./fft(akw,8000);
|
||||
subplot(211);
|
||||
plot(20*log10(abs(H(1:4000))),";LPC mag spec;");
|
||||
grid;
|
||||
subplot(212);
|
||||
plot(angle(H(1:4000))*180/pi,";LPC phase spec;");
|
||||
grid;
|
||||
if (k == 'p')
|
||||
% stops multimode errors from gnuplot, I know not why...
|
||||
figure(2);
|
||||
figure(5);
|
||||
|
||||
pngname = sprintf("%s_%d_lpc",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
% autocorrelation function to research voicing est
|
||||
|
||||
%M = length(s);
|
||||
%sw = s .* hanning(M)';
|
||||
%for k=0:159
|
||||
% R(k+1) = sw(1:320-k) * sw(1+k:320)';
|
||||
%endfor
|
||||
%figure(4);
|
||||
%R_label = sprintf(";R(k) %3.2f;",max(R(20:159))/R(1));
|
||||
%plot(R/R(1),R_label);
|
||||
%grid
|
||||
|
||||
figure(2);
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
|
||||
% optional print to PNG
|
||||
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,36 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% plpitch.m
|
||||
% Plots two pitch tracks on top of each other, used for comparing pitch
|
||||
% estimators
|
||||
|
||||
function plpitch(pitch1_name, pitch2_name, start_fr, end_fr)
|
||||
|
||||
pitch1 = load(pitch1_name);
|
||||
pitch2 = load(pitch2_name);
|
||||
|
||||
st = 1;
|
||||
en = length(pitch1);
|
||||
if (nargin >= 3)
|
||||
st = start_fr;
|
||||
endif
|
||||
if (nargin >= 4)
|
||||
en = end_fr;
|
||||
endif
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
l1 = strcat("r;",pitch1_name,";")
|
||||
l1
|
||||
st
|
||||
en
|
||||
plot(pitch1(st:en), l1);
|
||||
axis([1 en-st 20 160]);
|
||||
l2 = strcat("g;",pitch2_name,";");
|
||||
hold on;
|
||||
plot(pitch2(st:en),l2);
|
||||
hold off;
|
||||
endfunction
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot two sparse phase prediction error text files.
|
||||
% Generate data from print_pred_error, print_pred_error_sparse_wo_correction1 etc
|
||||
|
||||
function plppe(ppe1_file, ppe2_file, f)
|
||||
|
||||
ppe1 = load(ppe1_file);
|
||||
ppe2 = load(ppe2_file);
|
||||
|
||||
std1 = std(nonzeros(ppe1(:,40:80)));
|
||||
std2 = std(nonzeros(ppe2(:,40:80)));
|
||||
|
||||
printf("std dev for %s is %4.3f\n", ppe1_file, std1);
|
||||
printf("std dev for %s is %4.3f\n", ppe2_file, std2);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211)
|
||||
hist(nonzeros(ppe1(:,40:80)),20);
|
||||
subplot(212)
|
||||
hist(nonzeros(ppe2(:,40:80)),20);
|
||||
|
||||
k = ' ';
|
||||
do
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
L = length(nonzeros(ppe1(f,:)));
|
||||
x = (1:L)*4000/L;
|
||||
std1 = std(nonzeros(ppe1(f,:)));
|
||||
legend = sprintf(";std dev %4.3f;", std1);
|
||||
plot(x, nonzeros(ppe1(f,:)),legend);
|
||||
axis([0 4000 -pi pi]);
|
||||
subplot(212)
|
||||
std2 = std(nonzeros(ppe2(f,:)));
|
||||
legend = sprintf(";std dev %4.3f;", std2);
|
||||
plot(x, nonzeros(ppe2(f,:)),legend);
|
||||
axis([0 4000 -pi pi]);
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
|
||||
% optional print to PNG
|
||||
|
||||
if (k == 'p')
|
||||
pngname = sprintf("%s_%d",samname,f);
|
||||
png(pngname);
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
|
@ -1,35 +0,0 @@
|
|||
% Copyright David Rowe 2010
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
% plots the difference of two files
|
||||
|
||||
function plsub(samname1, samname2, start_sam, end_sam, pngname)
|
||||
|
||||
fs1=fopen(samname1,"rb");
|
||||
s1=fread(fs1,Inf,"short");
|
||||
fs2=fopen(samname2,"rb");
|
||||
s2=fread(fs2,Inf,"short");
|
||||
|
||||
st = 1;
|
||||
en = length(s1);
|
||||
if (nargin >= 3)
|
||||
st = start_sam;
|
||||
endif
|
||||
if (nargin >= 4)
|
||||
en = end_sam;
|
||||
endif
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
l1 = strcat("r;",samname1,";");
|
||||
plot(s1(st:en) - s2(st:en), l1);
|
||||
%axis([1 en-st min(s1(st:en)) max(s1(st:en))]);
|
||||
|
||||
if (nargin == 5)
|
||||
pngname = sprintf("%s.png",pngname);
|
||||
print(pngname, '-dpng', "-S500,500")
|
||||
pngname = sprintf("%s_large.png",pngname);
|
||||
print(pngname, '-dpng', "-S800,600")
|
||||
endif
|
||||
|
||||
endfunction
|
|
@ -1,89 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot voicing information from sample and dump files.
|
||||
%
|
||||
% samfilename is the raw source file, e.g. "../raw/hts1a.raw"
|
||||
% samname is the dumpfile prefix, e.g. "../src/hts1a"
|
||||
%
|
||||
% There is a 160 sample (two frame delay) from the when a sample
|
||||
% enters the input buffer until it is at the centre of the analysis window
|
||||
|
||||
function plvoicing(samfilename, samname, start_f, end_f, pngname)
|
||||
|
||||
fs=fopen(samfilename,"rb");
|
||||
s=fread(fs,Inf,"short");
|
||||
|
||||
snr_name = strcat(samname,"_snr.txt");
|
||||
snr = load(snr_name);
|
||||
model_name = strcat(samname,"_model.txt");
|
||||
model = load(model_name);
|
||||
|
||||
Wo = model((start_f+1):end_f,1);
|
||||
F0 = Wo*4000/pi;
|
||||
dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
|
||||
|
||||
% work out LP and HP energy
|
||||
|
||||
for f=(start_f+1):end_f
|
||||
L = model(f,2);
|
||||
Am = model(f,3:(L+2));
|
||||
L2 = floor(L/2);
|
||||
elow = Am(1:L2) * Am(1:L2)';
|
||||
ehigh = Am(L2:L) * Am(L2:L)';
|
||||
erat(f-(start_f+1)+1) = 10*log10(elow/ehigh);
|
||||
endfor
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
sp = s((start_f-2)*80:(end_f-2)*80);
|
||||
plot(sp);
|
||||
hold on;
|
||||
vhigh = snr((start_f+1):end_f) > 7;
|
||||
vlow = snr((start_f+1):end_f) > 4;
|
||||
|
||||
% test correction based on erat
|
||||
|
||||
vlowadj = vlow;
|
||||
|
||||
for f=1:length(erat)-1
|
||||
if (vlow(f) == 0)
|
||||
if (erat(f) > 10)
|
||||
vlowadj(f) = 1;
|
||||
endif
|
||||
endif
|
||||
if (vlow(f) == 1)
|
||||
if (erat(f) < -10)
|
||||
vlowadj(f) = 0;
|
||||
endif
|
||||
if (abs(dF0(f)) > 15)
|
||||
vlowadj(f) = 0;
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
x = 1:(end_f-start_f);
|
||||
plot(x*80,snr((start_f+1):end_f)*1000,';SNRdB x 1000;g+');
|
||||
plot(x*80,-8000 + vhigh*2000,';7dB thresh;g');
|
||||
plot(x*80,-11000 + vlowadj*2000,';vlow with corr;g');
|
||||
plot(x*80,erat*1000,';elow/ehigh in dB;r');
|
||||
plot(x*80,-14000 + vlow*2000,';4dB thresh;r');
|
||||
hold off;
|
||||
grid
|
||||
if (nargin == 5)
|
||||
print(pngname, "-dpng", "-S500,500")
|
||||
endif
|
||||
|
||||
figure(2)
|
||||
Wo = model((start_f+1):end_f,1);
|
||||
F0 = Wo*4000/pi;
|
||||
dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
|
||||
%plot(dF0,'+--')
|
||||
%hold on;
|
||||
%plot([ 1 length(dF0) ], [10 10] ,'r')
|
||||
%plot([ 1 length(dF0) ], [-10 -10] ,'r')
|
||||
%axis([1 length(dF0) -50 50])
|
||||
%hold off;
|
||||
plot(F0,'+--')
|
||||
endfunction
|
|
@ -1,25 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Replot current plot as a png, generates small and large versions
|
||||
|
||||
function png(pngname)
|
||||
% small image
|
||||
|
||||
__gnuplot_set__ terminal png size 420,300
|
||||
ss = sprintf("__gnuplot_set__ output \"%s.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% larger image
|
||||
|
||||
__gnuplot_set__ terminal png size 800,600
|
||||
ss = sprintf("__gnuplot_set__ output \"%s_large.png\"", pngname);
|
||||
eval(ss)
|
||||
replot;
|
||||
|
||||
% for some reason I need this to stop large plot getting wiped
|
||||
__gnuplot_set__ output "/dev/null"
|
||||
|
||||
endfunction
|
|
@ -1,24 +0,0 @@
|
|||
% Copyright David Rowe 2009
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
% Plot postfilter doing its thing
|
||||
|
||||
function postfilter(samname)
|
||||
p = load(samname);
|
||||
figure(1);
|
||||
plot(p(:,1),";energy;");
|
||||
hold on;
|
||||
plot(p(:,2),";bg_est;");
|
||||
hold off;
|
||||
grid;
|
||||
pngname=sprintf("%s_postfilter_1", samname);
|
||||
png(pngname);
|
||||
|
||||
figure(2);
|
||||
plot(p(:,3),";% unvoiced;");
|
||||
grid;
|
||||
pngname=sprintf("%s_postfilter_2", samname);
|
||||
png(pngname);
|
||||
endfunction
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
% pulse.m
|
||||
% David Rowe August 2009
|
||||
%
|
||||
% Experiments with human pulse perception for sinusoidal codecs
|
||||
|
||||
function pulse(samname)
|
||||
|
||||
A = 1000;
|
||||
K = 16000;
|
||||
N = 80;
|
||||
frames = K/N;
|
||||
s = zeros(1,K);
|
||||
|
||||
for f=1:frames
|
||||
% lets try placing np random pulses in every frame
|
||||
|
||||
P = 20 + (160-20)*rand(1,1);
|
||||
Wo = 2*pi/P;
|
||||
L = floor(pi/Wo);
|
||||
sf = zeros(1,N);
|
||||
for m=1:L/2:L
|
||||
pos = floor(rand(1,1)*N)+1;
|
||||
%pos = 50;
|
||||
for l=m:m+L/2-1
|
||||
sf = sf + A*cos(l*Wo*((f-1)*N+1:f*N) - pos*l*Wo);
|
||||
endfor
|
||||
endfor
|
||||
s((f-1)*N+1:f*N) = sf;
|
||||
endfor
|
||||
|
||||
plot(s(1:250));
|
||||
|
||||
fs=fopen(samname,"wb");
|
||||
fwrite(fs,s,"short");
|
||||
fclose(fs);
|
||||
endfunction
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
% sd.m
|
||||
% David Rowe Aug 2012
|
||||
% Plots the spectal distorion between twofiles of LPCs. Used for LSP
|
||||
% quantisation tuning.
|
||||
|
||||
function sd(raw_filename, dump_file_prefix, f)
|
||||
|
||||
ak1_filename = sprintf("%s_ak.txt", dump_file_prefix);
|
||||
ak2_filename = sprintf("%s_ak_.txt", dump_file_prefix);
|
||||
ak1 = load(ak1_filename);
|
||||
ak2 = load(ak2_filename);
|
||||
|
||||
[ak1_r, ak1_c] = size(ak1);
|
||||
[ak2_r, ak2_c] = size(ak1);
|
||||
|
||||
frames = max([ak1_r ak2_r]);
|
||||
sd = zeros(1,frames);
|
||||
Ndft = 512;
|
||||
A1 = zeros(frames, Ndft);
|
||||
A2 = zeros(frames, Ndft);
|
||||
|
||||
% initial helicopter view of all frames
|
||||
|
||||
for i = 1:frames
|
||||
A1(i,:) = -20*log10(abs(fft(ak1(i,:),Ndft)));
|
||||
A2(i,:) = -20*log10(abs(fft(ak2(i,:),Ndft)));
|
||||
sd(i) = sum((A1(i,:) - A2(i,:)).^2)/Ndft;
|
||||
end
|
||||
printf("sd av %3.2f dB*dB\n", sum(sd)/frames);
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211)
|
||||
fs=fopen(raw_filename,"rb");
|
||||
s = fread(fs,Inf,"short");
|
||||
plot(s);
|
||||
subplot(212)
|
||||
plot(sd);
|
||||
|
||||
% now enter single step mode so we can analyse each frame
|
||||
|
||||
sn_name = strcat(dump_file_prefix,"_sn.txt");
|
||||
Sn = load(sn_name);
|
||||
|
||||
lsp1_filename = sprintf("%s_lsp.txt", dump_file_prefix);
|
||||
lsp2_filename = sprintf("%s_lsp_.txt", dump_file_prefix);
|
||||
lsp1 = load(lsp1_filename);
|
||||
lsp2 = load(lsp2_filename);
|
||||
|
||||
weights_filename = sprintf("%s_weights.txt", dump_file_prefix);
|
||||
if file_in_path(".",weights_filename)
|
||||
weights = load(weights_filename);
|
||||
end
|
||||
|
||||
k = ' ';
|
||||
do
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211)
|
||||
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
|
||||
size(s);
|
||||
plot(s);
|
||||
axis([1 length(s) -20000 20000]);
|
||||
|
||||
subplot(212);
|
||||
plot((1:Ndft/2)*4000/(Ndft/2), A1(f,1:(Ndft/2)),";A1;r");
|
||||
axis([1 4000 -20 40]);
|
||||
hold on;
|
||||
plot((1:Ndft/2)*4000/(Ndft/2), A2(f,1:(Ndft/2)),";A2;");
|
||||
if file_in_path(".",weights_filename)
|
||||
plot(lsp1(f,:)*4000/pi, weights(f,:),";weights;g+");
|
||||
end
|
||||
|
||||
for l=1:10
|
||||
plot([lsp1(f,l)*4000/pi lsp1(f,l)*4000/pi], [0 -10], 'r');
|
||||
plot([lsp2(f,l)*4000/pi lsp2(f,l)*4000/pi], [-10 -20], 'b');
|
||||
endfor
|
||||
plot(0,0,';lsp1;r');
|
||||
plot(0,0,';lsp2;b');
|
||||
sd_str = sprintf(";sd %3.2f dB*dB;", sd(f));
|
||||
plot(0,0,sd_str);
|
||||
|
||||
hold off;
|
||||
|
||||
% interactive menu
|
||||
|
||||
printf("\rframe: %d menu: n-next b-back q-quit", f);
|
||||
fflush(stdout);
|
||||
k = kbhit();
|
||||
if (k == 'n')
|
||||
f = f + 1;
|
||||
endif
|
||||
if (k == 'b')
|
||||
f = f - 1;
|
||||
endif
|
||||
|
||||
until (k == 'q')
|
||||
printf("\n");
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
% spec.m
|
||||
% Jean Marc Valin
|
||||
%
|
||||
% Spectrogram function for Octave
|
||||
%
|
||||
% Copyright (c) John-Marc Valin 2012
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions
|
||||
% are met:
|
||||
%
|
||||
% - Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
%
|
||||
% - Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in the
|
||||
% documentation and/or other materials provided with the distribution.
|
||||
%
|
||||
% - Neither the name of Jean Marc Valin nor the names of its
|
||||
% contributors may be used to endorse or promote products derived from
|
||||
% this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
% ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function X = spec(x, Fs, framesize, start, stop)
|
||||
|
||||
|
||||
gr=[zeros(1024,1),[0:1023]'/1023,.68*[0:1023]'/1023];
|
||||
|
||||
%gr=[.4*[0:1023]'/1023,[0:1023]'/1023,.68*[0:1023]'/1023];
|
||||
|
||||
%t=[0:1023]'/1023;
|
||||
%t=(1+.25*t-cos(pi*t))/2.25;
|
||||
%gr = [zeros(1024,1),t,.68*t];
|
||||
|
||||
|
||||
%colormap(gr);
|
||||
|
||||
if nargin < 2 || isempty(Fs)
|
||||
Fs = 44100;
|
||||
end
|
||||
|
||||
if nargin < 3 || isempty(framesize)
|
||||
framesize = 2048;
|
||||
endif
|
||||
|
||||
offset = framesize/4;
|
||||
|
||||
X = 20*log10(abs(specgram(x, framesize, 48000, blackmanharris(framesize)', framesize-offset)));
|
||||
|
||||
XM=max(max(X));
|
||||
X = max(XM-120,X);
|
||||
%size(X)
|
||||
F = -[framesize/2-1:-1:0]/framesize*Fs;
|
||||
%F = [0:127]/128*24000;
|
||||
T=[1:size(X,2)]/Fs*offset;
|
||||
%imagesc(X(end:-1:1,:));
|
||||
|
||||
if nargin < 4 || isempty(start)
|
||||
istart=1;
|
||||
else
|
||||
istart = round(start*Fs/offset);
|
||||
end
|
||||
|
||||
if nargin < 5 || isempty(stop)
|
||||
istop = size(X,2);
|
||||
else
|
||||
istop = round(stop*Fs/offset);
|
||||
endif
|
||||
|
||||
istart = max(1,istart);
|
||||
istop = min(istop, size(X,2));
|
||||
|
||||
imagesc(T(1+istart:istop), F, X(end:-1:1,1+istart:istop));
|
||||
|
||||
X = X(:,1+istart:istop);
|
|
@ -1,306 +0,0 @@
|
|||
% tfdmdv.m
|
||||
%
|
||||
% Octave script that tests the C port of the FDMDV modem. This script loads
|
||||
% the output of unittest/tfdmdv.c and compares it to the output of the
|
||||
% reference versions of the same functions written in Octave.
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
fdmdv; % load modem code
|
||||
|
||||
% Generate reference vectors using Octave implementation of FDMDV modem
|
||||
|
||||
global passes;
|
||||
global fails;
|
||||
passes = fails = 0;
|
||||
frames = 25;
|
||||
prev_tx_symbols = ones(Nc+1,1);
|
||||
prev_rx_symbols = ones(Nc+1,1);
|
||||
foff_phase_rect = 1;
|
||||
coarse_fine = 0;
|
||||
fest_state = 0;
|
||||
channel = [];
|
||||
channel_count = 0;
|
||||
next_nin = M;
|
||||
sig_est = zeros(Nc+1,1);
|
||||
noise_est = zeros(Nc+1,1);
|
||||
|
||||
% Octave outputs we want to collect for comparison to C version
|
||||
|
||||
tx_bits_log = [];
|
||||
tx_symbols_log = [];
|
||||
tx_baseband_log = [];
|
||||
tx_fdm_log = [];
|
||||
pilot_baseband1_log = [];
|
||||
pilot_baseband2_log = [];
|
||||
pilot_lpf1_log = [];
|
||||
pilot_lpf2_log = [];
|
||||
S1_log = [];
|
||||
S2_log = [];
|
||||
foff_coarse_log = [];
|
||||
foff_fine_log = [];
|
||||
foff_log = [];
|
||||
rx_baseband_log = [];
|
||||
rx_filt_log = [];
|
||||
env_log = [];
|
||||
rx_timing_log = [];
|
||||
rx_symbols_log = [];
|
||||
rx_bits_log = [];
|
||||
sync_bit_log = [];
|
||||
coarse_fine_log = [];
|
||||
nin_log = [];
|
||||
sig_est_log = [];
|
||||
noise_est_log = [];
|
||||
|
||||
for f=1:frames
|
||||
|
||||
% modulator
|
||||
|
||||
tx_bits = get_test_bits(Nc*Nb);
|
||||
tx_bits_log = [tx_bits_log tx_bits];
|
||||
tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, 'dqpsk');
|
||||
prev_tx_symbols = tx_symbols;
|
||||
tx_symbols_log = [tx_symbols_log tx_symbols];
|
||||
tx_baseband = tx_filter(tx_symbols);
|
||||
tx_baseband_log = [tx_baseband_log tx_baseband];
|
||||
tx_fdm = fdm_upconvert(tx_baseband);
|
||||
tx_fdm_log = [tx_fdm_log tx_fdm];
|
||||
|
||||
% channel
|
||||
|
||||
nin = next_nin;
|
||||
%nin = 120;
|
||||
%nin = M;
|
||||
%if (f == 3)
|
||||
% nin = 120;
|
||||
%elseif (f == 4)
|
||||
% nin = 200;
|
||||
%else
|
||||
% nin = M;
|
||||
%end
|
||||
channel = [channel real(tx_fdm)];
|
||||
channel_count += M;
|
||||
rx_fdm = channel(1:nin);
|
||||
channel = channel(nin+1:channel_count);
|
||||
channel_count -= nin;
|
||||
|
||||
% demodulator
|
||||
|
||||
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
|
||||
|
||||
[foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
|
||||
if coarse_fine == 0
|
||||
foff = foff_coarse;
|
||||
end
|
||||
foff_coarse_log = [foff_coarse_log foff_coarse];
|
||||
|
||||
pilot_baseband1_log = [pilot_baseband1_log pilot_baseband1];
|
||||
pilot_baseband2_log = [pilot_baseband2_log pilot_baseband2];
|
||||
pilot_lpf1_log = [pilot_lpf1_log pilot_lpf1];
|
||||
pilot_lpf2_log = [pilot_lpf2_log pilot_lpf2];
|
||||
S1_log = [S1_log S1];
|
||||
S2_log = [S2_log S2];
|
||||
|
||||
foff_rect = exp(j*2*pi*foff/Fs);
|
||||
|
||||
for i=1:nin
|
||||
foff_phase_rect *= foff_rect';
|
||||
rx_fdm_fcorr(i) = rx_fdm(i)*foff_phase_rect;
|
||||
end
|
||||
|
||||
rx_baseband = fdm_downconvert(rx_fdm_fcorr, nin);
|
||||
rx_baseband_log = [rx_baseband_log rx_baseband];
|
||||
|
||||
rx_filt = rx_filter(rx_baseband, nin);
|
||||
rx_filt_log = [rx_filt_log rx_filt];
|
||||
|
||||
[rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin);
|
||||
env_log = [env_log env];
|
||||
|
||||
rx_timing_log = [rx_timing_log rx_timing];
|
||||
rx_symbols_log = [rx_symbols_log rx_symbols];
|
||||
|
||||
next_nin = M;
|
||||
if rx_timing > 2*M/P
|
||||
next_nin += M/P;
|
||||
end
|
||||
if rx_timing < 0;
|
||||
next_nin -= M/P;
|
||||
end
|
||||
nin_log = [nin_log nin];
|
||||
|
||||
[rx_bits sync_bit foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk');
|
||||
|
||||
[sig_est noise_est] = snr_update(sig_est, noise_est, pd);
|
||||
sig_est_log = [sig_est_log sig_est];
|
||||
noise_est_log = [noise_est_log noise_est];
|
||||
|
||||
prev_rx_symbols = rx_symbols;
|
||||
rx_bits_log = [rx_bits_log rx_bits];
|
||||
foff_fine_log = [foff_fine_log foff_fine];
|
||||
sync_bit_log = [sync_bit_log sync_bit];
|
||||
foff -= 0.5*foff_fine;
|
||||
foff_log = [foff_log foff];
|
||||
|
||||
% freq est state machine
|
||||
|
||||
[coarse_fine fest_state] = freq_state(sync_bit, fest_state);
|
||||
coarse_fine_log = [coarse_fine_log coarse_fine];
|
||||
end
|
||||
|
||||
% Compare to the output from the C version
|
||||
|
||||
load ../unittest/tfdmdv_out.txt
|
||||
|
||||
% Helper functions to plot output of C verson and difference between Octave and C versions
|
||||
|
||||
function stem_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec)
|
||||
figure(plotnum)
|
||||
subplot(subplotnum)
|
||||
stem(sig);
|
||||
hold on;
|
||||
stem(error,'g');
|
||||
hold off;
|
||||
if nargin == 6
|
||||
axis(axisvec);
|
||||
end
|
||||
title(titlestr);
|
||||
endfunction
|
||||
|
||||
function plot_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec)
|
||||
figure(plotnum)
|
||||
subplot(subplotnum)
|
||||
plot(sig);
|
||||
hold on;
|
||||
plot(error,'g');
|
||||
hold off;
|
||||
if nargin == 6
|
||||
axis(axisvec);
|
||||
end
|
||||
title(titlestr);
|
||||
endfunction
|
||||
|
||||
% ---------------------------------------------------------------------------------------
|
||||
% Plot output and test each C function
|
||||
% ---------------------------------------------------------------------------------------
|
||||
|
||||
% fdmdv_get_test_bits() & bits_to_dqpsk_symbols()
|
||||
|
||||
n = 28;
|
||||
stem_sig_and_error(1, 211, tx_bits_log_c(1:n), tx_bits_log(1:n) - tx_bits_log_c(1:n), 'tx bits', [1 n -1.5 1.5])
|
||||
stem_sig_and_error(1, 212, real(tx_symbols_log_c(1:n/2)), real(tx_symbols_log(1:n/2) - tx_symbols_log_c(1:n/2)), 'tx symbols real', [1 n/2 -1.5 1.5])
|
||||
|
||||
% tx_filter()
|
||||
|
||||
diff = tx_baseband_log - tx_baseband_log_c;
|
||||
c=15;
|
||||
plot_sig_and_error(2, 211, real(tx_baseband_log_c(c,:)), real(sum(diff)), 'tx baseband real')
|
||||
plot_sig_and_error(2, 212, imag(tx_baseband_log_c(c,:)), imag(sum(diff)), 'tx baseband imag')
|
||||
|
||||
% fdm_upconvert()
|
||||
|
||||
plot_sig_and_error(3, 211, real(tx_fdm_log_c), real(tx_fdm_log - tx_fdm_log_c), 'tx fdm real')
|
||||
plot_sig_and_error(3, 212, imag(tx_fdm_log_c), imag(tx_fdm_log - tx_fdm_log_c), 'tx fdm imag')
|
||||
|
||||
% generate_pilot_lut()
|
||||
|
||||
plot_sig_and_error(4, 211, real(pilot_lut_c), real(pilot_lut - pilot_lut_c), 'pilot lut real')
|
||||
plot_sig_and_error(4, 212, imag(pilot_lut_c), imag(pilot_lut - pilot_lut_c), 'pilot lut imag')
|
||||
|
||||
% rx_est_freq_offset()
|
||||
|
||||
st=1; en = 3*Npilotbaseband;
|
||||
plot_sig_and_error(5, 211, real(pilot_baseband1_log(st:en)), real(pilot_baseband1_log(st:en) - pilot_baseband1_log_c(st:en)), 'pilot baseband1 real' )
|
||||
plot_sig_and_error(5, 212, real(pilot_baseband2_log(st:en)), real(pilot_baseband2_log(st:en) - pilot_baseband2_log_c(st:en)), 'pilot baseband2 real' )
|
||||
|
||||
st=1; en = 3*Npilotlpf;
|
||||
plot_sig_and_error(6, 211, real(pilot_lpf1_log(st:en)), real(pilot_lpf1_log(st:en) - pilot_lpf1_log_c(st:en)), 'pilot lpf1 real' )
|
||||
plot_sig_and_error(6, 212, real(pilot_lpf2_log(st:en)), real(pilot_lpf2_log(st:en) - pilot_lpf2_log_c(st:en)), 'pilot lpf2 real' )
|
||||
|
||||
plot_sig_and_error(7, 211, real(S1_log), real(S1_log - S1_log_c), 'S1 real' )
|
||||
plot_sig_and_error(7, 212, imag(S1_log), imag(S1_log - S1_log_c), 'S1 imag' )
|
||||
|
||||
plot_sig_and_error(8, 211, real(S2_log), real(S2_log - S2_log_c), 'S2 real' )
|
||||
plot_sig_and_error(8, 212, imag(S2_log), imag(S2_log - S2_log_c), 'S2 imag' )
|
||||
|
||||
plot_sig_and_error(9, 211, foff_coarse_log, foff_coarse_log - foff_coarse_log_c, 'Coarse Freq Offset' )
|
||||
plot_sig_and_error(9, 212, foff_fine_log, foff_fine_log - foff_fine_log_c, 'Fine Freq Offset' )
|
||||
|
||||
plot_sig_and_error(10, 211, foff_log, foff_log - foff_log_c, 'Freq Offset' )
|
||||
plot_sig_and_error(10, 212, coarse_fine_log, coarse_fine_log - coarse_fine_log_c, 'Freq Est Coarse(0) Fine(1)', [1 frames -0.5 1.5] )
|
||||
|
||||
c=15;
|
||||
plot_sig_and_error(11, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' )
|
||||
plot_sig_and_error(11, 212, imag(rx_baseband_log(c,:)), imag(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband imag' )
|
||||
|
||||
plot_sig_and_error(12, 211, real(rx_filt_log(c,:)), real(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt real' )
|
||||
plot_sig_and_error(12, 212, imag(rx_filt_log(c,:)), imag(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt imag' )
|
||||
|
||||
st=1; en=3*Nt*P;
|
||||
plot_sig_and_error(13, 211, env_log(st:en), env_log(st:en) - env_log_c(st:en), 'env' )
|
||||
stem_sig_and_error(13, 212, real(rx_symbols_log(c,:)), real(rx_symbols_log(c,:) - rx_symbols_log_c(c,:)), 'rx symbols' )
|
||||
|
||||
st=10*28;
|
||||
en = 12*28;
|
||||
plot_sig_and_error(14, 211, rx_timing_log, rx_timing_log - rx_timing_log_c, 'Rx Timing' )
|
||||
stem_sig_and_error(14, 212, sync_bit_log_c, sync_bit_log - sync_bit_log_c, 'Sync bit', [1 n -1.5 1.5])
|
||||
|
||||
stem_sig_and_error(15, 211, rx_bits_log_c(st:en), rx_bits_log(st:en) - rx_bits_log_c(st:en), 'RX bits', [1 en-st -1.5 1.5])
|
||||
stem_sig_and_error(15, 212, nin_log_c, nin_log - nin_log_c, 'nin')
|
||||
|
||||
c = 1;
|
||||
plot_sig_and_error(16, 211, sig_est_log(c,:), sig_est_log(c,:) - sig_est_log_c(c,:), 'sig est for SNR' )
|
||||
plot_sig_and_error(16, 212, noise_est_log(c,:), noise_est_log(c,:) - noise_est_log_c(c,:), 'noise est for SNR' )
|
||||
|
||||
% ---------------------------------------------------------------------------------------
|
||||
% AUTOMATED CHECKS ------------------------------------------
|
||||
% ---------------------------------------------------------------------------------------
|
||||
|
||||
function check(a, b, test_name)
|
||||
global passes;
|
||||
global fails;
|
||||
|
||||
[m n] = size(a);
|
||||
printf("%s", test_name);
|
||||
for i=1:(25-length(test_name))
|
||||
printf(".");
|
||||
end
|
||||
printf(": ");
|
||||
|
||||
if sum(abs(a - b))/n < 1E-3
|
||||
printf("OK\n");
|
||||
passes++;
|
||||
else
|
||||
printf("FAIL\n");
|
||||
fails++;
|
||||
end
|
||||
endfunction
|
||||
|
||||
check(tx_bits_log, tx_bits_log_c, 'tx_bits');
|
||||
check(tx_symbols_log, tx_symbols_log_c, 'tx_symbols');
|
||||
check(tx_baseband_log, tx_baseband_log_c, 'tx_baseband');
|
||||
check(tx_fdm_log, tx_fdm_log_c, 'tx_fdm');
|
||||
check(pilot_lut, pilot_lut_c, 'pilot_lut');
|
||||
check(pilot_baseband1_log, pilot_baseband1_log_c, 'pilot lpf1');
|
||||
check(pilot_baseband2_log, pilot_baseband2_log_c, 'pilot lpf2');
|
||||
check(S1_log, S1_log_c, 'S1');
|
||||
check(S2_log, S2_log_c, 'S2');
|
||||
check(foff_coarse_log, foff_coarse_log_c, 'foff_coarse');
|
||||
check(foff_fine_log, foff_fine_log_c, 'foff_fine');
|
||||
check(foff_log, foff_log_c, 'foff');
|
||||
check(rx_baseband_log, rx_baseband_log_c, 'rx baseband');
|
||||
check(rx_filt_log, rx_filt_log_c, 'rx filt');
|
||||
check(env_log, env_log_c, 'env');
|
||||
check(rx_timing_log, rx_timing_log_c, 'rx_timing');
|
||||
check(rx_symbols_log, rx_symbols_log_c, 'rx_symbols');
|
||||
check(rx_bits_log, rx_bits_log_c, 'rx bits');
|
||||
check(sync_bit_log, sync_bit_log_c, 'sync bit');
|
||||
check(coarse_fine_log, coarse_fine_log_c, 'coarse_fine');
|
||||
check(nin_log, nin_log_c, 'nin');
|
||||
check(sig_est_log, sig_est_log_c, 'sig_est');
|
||||
check(noise_est_log, noise_est_log_c, 'noise_est');
|
||||
|
||||
printf("\npasses: %d fails: %d\n", passes, fails);
|
|
@ -1,49 +0,0 @@
|
|||
% tget-spec.m
|
||||
%
|
||||
% Used in conjunction with src/fdmdv_demod to test the
|
||||
% fdmdv_get_rx_spectrum() function.
|
||||
%
|
||||
% codec2-dev/src$ ./fdmdv_demod fdmdv_mod.raw tmp.c2 dump.txt
|
||||
% octave:3> tget_spec("../src/dump.txt")
|
||||
%
|
||||
% Copyright David Rowe 2012
|
||||
% This program is distributed under the terms of the GNU General Public License
|
||||
% Version 2
|
||||
%
|
||||
|
||||
function tfft_log(dumpfilename)
|
||||
|
||||
load(dumpfilename);
|
||||
|
||||
[rows cols] = size(rx_spec_log_c);
|
||||
Fs = 8000; low_freq = 0; high_freq = 2500;
|
||||
res = (Fs/2)/cols;
|
||||
st_bin = low_freq/res + 1;
|
||||
en_bin = high_freq/res;
|
||||
xaxis = (st_bin:en_bin)*res;
|
||||
|
||||
f_start = 2; f_end = 100;
|
||||
beta = 0.1;
|
||||
|
||||
av = zeros(f_end, en_bin-st_bin+1);
|
||||
for r=f_start:f_end
|
||||
x = (1-beta)*av(r-1,:) + beta*rx_spec_log_c(r,st_bin:en_bin);
|
||||
av(r,:) = x;
|
||||
end
|
||||
|
||||
% spectrogram (waterfall)
|
||||
|
||||
figure(1)
|
||||
clf;
|
||||
imagesc(av,[-40 0]);
|
||||
|
||||
% animated spectrum display
|
||||
|
||||
figure(2)
|
||||
clf;
|
||||
for r=f_start:f_end
|
||||
plot(xaxis, av(r,:))
|
||||
axis([ low_freq high_freq -40 0])
|
||||
sleep(0.1)
|
||||
end
|
||||
endfunction
|
|
@ -1,52 +0,0 @@
|
|||
% twotone.m
|
||||
% David Rowe Aug 2012
|
||||
% Used to experiment with combining phase of two tones
|
||||
|
||||
function cbphase
|
||||
|
||||
Wo = 100.0*pi/4000;
|
||||
L = floor(pi/Wo);
|
||||
phi = zeros(1,L);
|
||||
|
||||
% two harmonics
|
||||
|
||||
a = 20; b = 21;
|
||||
|
||||
% set up phases to whatever
|
||||
|
||||
phi(a) = -pi;
|
||||
phi(b) = -pi/2;
|
||||
|
||||
% synthesis the two-tone signal
|
||||
|
||||
N = 16000;
|
||||
Nplot = 250;
|
||||
s = zeros(1,N);
|
||||
|
||||
for m=a:b
|
||||
s_m = cos(m*Wo*(0:(N-1)) + phi(m));
|
||||
s = s + s_m;
|
||||
endfor
|
||||
|
||||
% now our theory says that this signal should be the same perceptually
|
||||
|
||||
phi_(a) = (phi(a) - phi(b))/2;
|
||||
phi_(b) = (phi(b) - phi(a))/2;
|
||||
|
||||
s_ = zeros(1,N);
|
||||
for m=a:b
|
||||
s_m = cos(m*Wo*(0:(N-1)) + phi_(m));
|
||||
s_ = s_ + s_m;
|
||||
endfor
|
||||
|
||||
% plot them and see if envelope has the same phase, but "carriers"
|
||||
% have different phase
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211);
|
||||
plot(s(1:Nplot));
|
||||
subplot(212);
|
||||
plot(s_(1:Nplot),'r');
|
||||
endfunction
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
% twotone1.m
|
||||
% David Rowe Aug 17 2012
|
||||
%
|
||||
% Used to experiment with combining phase of two tones. This version
|
||||
% sets up a complete synthetic speech signal then tries to combine the
|
||||
% phase of high frequency tones. Lets see if we can do this and keep perceptual
|
||||
% nature of signal the same.
|
||||
|
||||
function twotone1
|
||||
|
||||
% hts1a frame 47
|
||||
|
||||
Wo = 0.093168;
|
||||
L = 33;
|
||||
%A = [69.626907 460.218536 839.677429 2577.498047 972.647888 712.755066 489.048553 364.830536 409.230652 371.767487 489.112854 893.127014 2447.596680 752.878113 475.720520 234.452271 248.161606 232.171051 202.669891 323.914490 678.749451 362.958038 211.652512 170.764435 148.631790 169.261673 272.254150 176.872375 67.344391 99.022301 60.812035 34.319073 14.864757];
|
||||
A = zeros(1,L)*100;
|
||||
phi = [1.560274 1.508063 -1.565184 1.289117 -2.547365 1.412528 -1.303992 3.121130 1.087573 -1.158161 -2.928007 0.995093 -2.614023 0.246136 -2.267406 2.143802 -0.273431 -2.266897 1.685171 -0.668712 2.699722 -1.151891 2.406379 -0.046192 -2.718611 0.761067 -2.305014 0.133172 -1.428978 1.492630 -1.668385 1.539734 -1.336615];
|
||||
%phi = zeros(1,L);
|
||||
st = floor(L/2);
|
||||
%st = 1;
|
||||
|
||||
A(st:st+5) = 1000;
|
||||
|
||||
% now set up phase of signal with phase of upper frequency harmonic
|
||||
% pairs combined
|
||||
|
||||
phi_ = phi;
|
||||
for m=floor(L/2):2:L
|
||||
phi_(m) = (phi(m) - phi(m+1))/2;
|
||||
phi_(m+1) = (phi(m+1) - phi(m))/2;
|
||||
%phi_(m+1) = 0;
|
||||
end
|
||||
|
||||
% synthesise the signals
|
||||
|
||||
N = 16000;
|
||||
Nplot = 250;
|
||||
|
||||
s = zeros(1,N);
|
||||
for m=st:L
|
||||
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m));
|
||||
s = s + s_m;
|
||||
endfor
|
||||
|
||||
s_ = zeros(1,N);
|
||||
for m=st:L
|
||||
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi_(m));
|
||||
s_ = s_ + s_m;
|
||||
endfor
|
||||
|
||||
% plot them, expect to see similar time domain waveforms
|
||||
|
||||
figure(1);
|
||||
clf;
|
||||
subplot(211);
|
||||
plot(s(1:Nplot));
|
||||
subplot(212);
|
||||
plot(s_(1:Nplot),'r');
|
||||
|
||||
figure(2);
|
||||
clf;
|
||||
subplot(211);
|
||||
plot(s(1:Nplot)-s_(1:Nplot));
|
||||
|
||||
% save to disk
|
||||
|
||||
gain = 1;
|
||||
fs=fopen("twotone1_orig.raw","wb");
|
||||
fwrite(fs,gain*s,"short");
|
||||
fclose(fs);
|
||||
fs=fopen("twotone1_comb.raw","wb");
|
||||
fwrite(fs,gain*s_,"short");
|
||||
fclose(fs);
|
||||
|
||||
endfunction
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
% undersample.m
|
||||
% David Rowe 5 Nov 2012
|
||||
% Testing algorithms for plotting undersampled data for fdmdv2 waveform displays
|
||||
|
||||
fs=fopen("../raw/hts1a.raw","rb");
|
||||
s = fread(fs,Inf,"short");
|
||||
|
||||
Fs1=8000;
|
||||
Fs2=200;
|
||||
|
||||
M=Fs1/Fs2;
|
||||
|
||||
samples=length(s)/M;
|
||||
s1=zeros(1,2*samples);
|
||||
for b=1:samples
|
||||
st = (b-1)*M + 1;
|
||||
en = b*M;
|
||||
s1(2*b-1) = max(s(st:en));
|
||||
s1(2*b) = min(s(st:en));
|
||||
end
|
||||
|
||||
subplot(211)
|
||||
plot(s)
|
||||
subplot(212)
|
||||
plot(s1);
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
111.627907
|
||||
97.959183
|
||||
97.959183
|
||||
97.959183
|
||||
87.272736
|
||||
78.048775
|
||||
112.280701
|
||||
120.000008
|
||||
61.538464
|
||||
68.817207
|
||||
84.210526
|
||||
90.140846
|
||||
90.140846
|
||||
90.140846
|
||||
101.587303
|
||||
80.000000
|
||||
72.727272
|
||||
95.522392
|
||||
90.140846
|
||||
90.140846
|
||||
101.587303
|
||||
90.140846
|
||||
85.333336
|
||||
86.486488
|
||||
91.428574
|
||||
91.428574
|
||||
91.428574
|
||||
91.428574
|
||||
91.428574
|
||||
90.140846
|
||||
86.486488
|
||||
86.486488
|
||||
85.333336
|
||||
85.333336
|
||||
85.333336
|
||||
81.012657
|
||||
74.418610
|
||||
71.111115
|
||||
71.111115
|
||||
71.111115
|
||||
71.111115
|
||||
68.085106
|
||||
68.085106
|
||||
67.368423
|
||||
67.368423
|
||||
70.329674
|
||||
70.329674
|
||||
70.329674
|
||||
71.111115
|
||||
74.418610
|
||||
74.418610
|
||||
75.294121
|
||||
79.012352
|
||||
85.333336
|
||||
96.969704
|
||||
111.627907
|
||||
111.627907
|
||||
120.000008
|
||||
111.627907
|
||||
104.347832
|
||||
104.347832
|
||||
97.959183
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
97.959183
|
||||
97.959183
|
||||
112.280701
|
||||
112.280701
|
||||
96.969704
|
||||
96.969704
|
||||
96.969704
|
||||
110.344841
|
||||
104.347832
|
||||
97.959183
|
||||
97.959183
|
||||
104.347832
|
||||
97.959183
|
||||
104.347832
|
||||
120.000008
|
||||
104.347832
|
||||
120.000008
|
||||
120.000008
|
||||
97.959183
|
||||
83.116882
|
||||
75.294121
|
||||
71.910118
|
||||
71.910110
|
||||
71.910110
|
||||
71.910110
|
||||
75.294121
|
||||
76.190483
|
||||
80.000008
|
||||
80.000008
|
||||
84.210526
|
||||
85.333336
|
||||
90.140846
|
||||
101.587303
|
||||
108.474571
|
||||
104.347832
|
||||
120.000008
|
||||
120.000008
|
||||
104.347832
|
||||
104.347832
|
||||
71.111115
|
||||
88.888893
|
||||
75.294121
|
||||
111.627907
|
||||
120.000008
|
||||
120.000008
|
||||
97.959183
|
||||
111.627907
|
||||
111.627907
|
||||
111.627907
|
||||
97.959183
|
||||
92.307693
|
||||
92.307693
|
||||
92.307693
|
||||
92.307693
|
||||
120.000008
|
||||
111.627907
|
||||
111.627907
|
||||
86.486488
|
||||
85.333336
|
||||
85.333336
|
||||
90.140846
|
||||
95.522392
|
||||
101.587311
|
||||
101.587311
|
||||
104.918037
|
||||
104.347832
|
||||
104.347832
|
||||
111.627907
|
||||
120.000008
|
||||
97.959183
|
||||
104.347832
|
||||
111.627907
|
||||
88.888893
|
||||
80.000000
|
||||
81.012657
|
||||
85.333336
|
||||
85.333336
|
||||
86.486488
|
||||
91.428574
|
||||
90.140846
|
||||
91.428574
|
||||
96.969704
|
||||
96.969704
|
||||
95.522392
|
||||
95.522392
|
||||
95.522392
|
||||
96.969704
|
||||
96.969704
|
||||
98.461533
|
||||
104.918022
|
||||
97.959183
|
||||
97.959183
|
||||
97.959183
|
||||
104.347832
|
||||
120.000008
|
||||
120.000008
|
||||
92.307693
|
||||
92.307693
|
||||
77.108429
|
||||
79.012344
|
||||
75.294121
|
||||
75.294121
|
||||
76.190483
|
||||
76.190483
|
||||
80.000008
|
||||
81.012657
|
||||
85.333336
|
||||
85.333336
|
||||
85.333336
|
||||
85.333336
|
||||
85.333336
|
||||
90.140846
|
||||
90.140846
|
||||
91.428574
|
||||
96.969704
|
||||
98.461533
|
||||
120.000008
|
||||
120.000008
|
||||
104.347832
|
||||
97.959183
|
||||
97.959183
|
||||
104.918037
|
||||
120.000008
|
||||
120.000008
|
||||
120.000008
|
||||
104.347832
|
||||
92.307693
|
||||
72.727272
|
||||
72.727272
|
||||
76.190483
|
||||
84.210533
|
||||
88.888901
|
||||
120.000008
|
||||
104.347832
|
||||
120.000008
|
||||
120.000008
|
||||
111.627907
|
||||
92.307693
|
||||
97.959183
|
||||
97.959183
|
||||
111.627907
|
||||
120.000008
|
||||
120.000008
|
||||
97.959183
|
||||
97.959183
|
||||
104.347832
|
||||
104.347832
|
||||
104.347832
|
||||
111.627907
|
||||
120.000008
|
||||
97.959183
|
||||
104.347832
|
||||
97.959183
|
||||
97.959183
|
||||
84.210526
|
||||
94.117653
|
||||
96.969704
|
||||
110.344841
|
||||
120.000008
|
||||
97.959183
|
||||
97.959183
|
||||
104.347832
|
||||
97.959183
|
||||
104.347832
|
||||
97.959183
|
||||
97.959183
|
||||
111.627907
|
||||
120.000008
|
||||
92.307693
|
||||
92.307693
|
||||
98.461533
|
||||
98.461533
|
||||
104.918022
|
||||
111.627907
|
||||
111.627907
|
||||
92.307693
|
||||
97.959183
|
||||
92.307693
|
||||
92.307693
|
||||
92.307693
|
||||
92.307693
|
||||
92.307693
|
||||
57.657658
|
||||
90.140846
|
||||
90.140846
|
||||
95.522392
|
||||
101.587311
|
||||
101.587311
|
||||
108.474586
|
||||
111.627907
|
||||
97.959183
|
||||
111.627907
|
||||
120.000008
|
||||
92.307693
|
||||
74.418610
|
||||
74.418610
|
||||
74.418610
|
||||
74.418610
|
||||
76.190483
|
||||
72.727280
|
||||
76.190483
|
||||
76.190483
|
||||
69.565224
|
||||
66.666672
|
||||
54.700855
|
||||
56.637169
|
||||
56.637169
|
||||
71.910110
|
||||
90.140846
|
||||
90.140846
|
||||
72.727272
|
||||
72.727272
|
||||
72.727272
|
||||
72.727272
|
||||
55.172413
|
||||
57.142857
|
||||
55.172413
|
||||
90.140846
|
||||
95.522392
|
||||
101.587311
|
||||
101.587311
|
||||
71.910110
|
||||
74.418610
|
||||
46.376812
|
||||
40.000000
|
||||
95.522392
|
||||
0
|
||||
0
|
|
@ -1,300 +0,0 @@
|
|||
0.0000000e+000
|
||||
9.2753623e+001
|
||||
5.4237288e+001
|
||||
8.5906040e+001
|
||||
7.0329670e+001
|
||||
5.5652174e+001
|
||||
5.4237288e+001
|
||||
5.4935622e+001
|
||||
5.4700855e+001
|
||||
7.5739645e+001
|
||||
7.3563218e+001
|
||||
1.2307692e+002
|
||||
1.1428571e+002
|
||||
7.3563218e+001
|
||||
7.7108434e+001
|
||||
1.8550725e+002
|
||||
1.2673267e+002
|
||||
1.0847458e+002
|
||||
7.8527607e+001
|
||||
8.8888889e+001
|
||||
8.3116883e+001
|
||||
8.1012658e+001
|
||||
1.0756303e+002
|
||||
1.3061224e+002
|
||||
4.8301887e+001
|
||||
4.7940075e+001
|
||||
4.8120301e+001
|
||||
4.9230769e+001
|
||||
4.9420849e+001
|
||||
4.6886447e+001
|
||||
4.2953020e+001
|
||||
3.9263804e+001
|
||||
3.7869822e+001
|
||||
3.5457064e+001
|
||||
3.4224599e+001
|
||||
3.3333333e+001
|
||||
3.2820513e+001
|
||||
3.2000000e+001
|
||||
3.1295844e+001
|
||||
2.9906542e+001
|
||||
2.9493088e+001
|
||||
2.9090909e+001
|
||||
2.8699552e+001
|
||||
2.8131868e+001
|
||||
2.7826087e+001
|
||||
2.7826087e+001
|
||||
2.7826087e+001
|
||||
2.8193833e+001
|
||||
2.7467811e+001
|
||||
2.6890756e+001
|
||||
5.4468085e+001
|
||||
5.4237288e+001
|
||||
6.4974619e+001
|
||||
1.0756303e+002
|
||||
8.8888889e+001
|
||||
1.0406504e+002
|
||||
4.4599303e+001
|
||||
5.4468085e+001
|
||||
3.6260623e+001
|
||||
3.6260623e+001
|
||||
8.1012658e+001
|
||||
7.0329670e+001
|
||||
1.2929293e+002
|
||||
9.9224806e+001
|
||||
4.3097643e+001
|
||||
4.4137931e+001
|
||||
4.5714286e+001
|
||||
4.7407407e+001
|
||||
4.8301887e+001
|
||||
4.9230769e+001
|
||||
4.9420849e+001
|
||||
5.0996016e+001
|
||||
5.1405622e+001
|
||||
5.1405622e+001
|
||||
5.2244898e+001
|
||||
5.2459016e+001
|
||||
5.2459016e+001
|
||||
5.2244898e+001
|
||||
5.3333333e+001
|
||||
5.2459016e+001
|
||||
5.2244898e+001
|
||||
5.1405622e+001
|
||||
5.1405622e+001
|
||||
5.1200000e+001
|
||||
5.0996016e+001
|
||||
5.0196078e+001
|
||||
4.9230769e+001
|
||||
4.9230769e+001
|
||||
4.9230769e+001
|
||||
4.9420849e+001
|
||||
4.9230769e+001
|
||||
4.9042146e+001
|
||||
9.8461538e+001
|
||||
1.0158730e+002
|
||||
5.1821862e+001
|
||||
9.0140845e+001
|
||||
1.0491803e+002
|
||||
1.4382022e+002
|
||||
5.2459016e+001
|
||||
5.2459016e+001
|
||||
1.2929293e+002
|
||||
1.6410256e+002
|
||||
8.0000000e+001
|
||||
7.3563218e+001
|
||||
1.0158730e+002
|
||||
9.9224806e+001
|
||||
4.9042146e+001
|
||||
4.9042146e+001
|
||||
4.9042146e+001
|
||||
5.9259259e+001
|
||||
1.4382022e+002
|
||||
7.2316384e+001
|
||||
1.0847458e+002
|
||||
1.1228070e+002
|
||||
1.6202532e+002
|
||||
8.1528662e+001
|
||||
7.2727273e+001
|
||||
1.8550725e+002
|
||||
6.0093897e+001
|
||||
1.0847458e+002
|
||||
8.9510490e+001
|
||||
7.1508380e+001
|
||||
4.0125392e+001
|
||||
4.0634921e+001
|
||||
4.0634921e+001
|
||||
4.0251572e+001
|
||||
4.0506329e+001
|
||||
4.3986254e+001
|
||||
4.0506329e+001
|
||||
9.8461538e+001
|
||||
5.6140351e+001
|
||||
6.5641026e+001
|
||||
5.4237288e+001
|
||||
1.1636364e+002
|
||||
3.4316354e+001
|
||||
3.4972678e+001
|
||||
3.7758112e+001
|
||||
4.0634921e+001
|
||||
4.0506329e+001
|
||||
4.1290323e+001
|
||||
4.2524917e+001
|
||||
4.3389831e+001
|
||||
4.4599303e+001
|
||||
4.4912281e+001
|
||||
4.6545455e+001
|
||||
4.7232472e+001
|
||||
4.8301887e+001
|
||||
4.9230769e+001
|
||||
4.9420849e+001
|
||||
5.0393701e+001
|
||||
5.1405622e+001
|
||||
5.3333333e+001
|
||||
5.3112033e+001
|
||||
1.1034483e+002
|
||||
9.7709924e+001
|
||||
1.4382022e+002
|
||||
5.0996016e+001
|
||||
5.1821862e+001
|
||||
5.0996016e+001
|
||||
5.2032520e+001
|
||||
5.3112033e+001
|
||||
5.3556485e+001
|
||||
5.4468085e+001
|
||||
5.5652174e+001
|
||||
5.4700855e+001
|
||||
5.4700855e+001
|
||||
5.4935622e+001
|
||||
5.4700855e+001
|
||||
5.4700855e+001
|
||||
5.4468085e+001
|
||||
5.4468085e+001
|
||||
5.4468085e+001
|
||||
5.4468085e+001
|
||||
5.3333333e+001
|
||||
5.1405622e+001
|
||||
5.0996016e+001
|
||||
5.0000000e+001
|
||||
4.8120301e+001
|
||||
4.8669202e+001
|
||||
4.7058824e+001
|
||||
4.6376812e+001
|
||||
4.5070423e+001
|
||||
4.4912281e+001
|
||||
4.4137931e+001
|
||||
4.2809365e+001
|
||||
4.2666667e+001
|
||||
4.2105263e+001
|
||||
4.1423948e+001
|
||||
4.1290323e+001
|
||||
4.1290323e+001
|
||||
4.1290323e+001
|
||||
4.0634921e+001
|
||||
4.0634921e+001
|
||||
4.0634921e+001
|
||||
4.0634921e+001
|
||||
4.0764331e+001
|
||||
4.1423948e+001
|
||||
4.2953020e+001
|
||||
4.5551601e+001
|
||||
1.7534247e+002
|
||||
4.7232472e+001
|
||||
1.3763441e+002
|
||||
1.3061224e+002
|
||||
4.5551601e+001
|
||||
4.3686007e+001
|
||||
4.8669202e+001
|
||||
9.4117647e+001
|
||||
8.1012658e+001
|
||||
1.1228070e+002
|
||||
1.3617021e+002
|
||||
4.3097643e+001
|
||||
4.3835616e+001
|
||||
4.6376812e+001
|
||||
4.6545455e+001
|
||||
4.6043165e+001
|
||||
4.8301887e+001
|
||||
4.9042146e+001
|
||||
4.9420849e+001
|
||||
5.1200000e+001
|
||||
5.1405622e+001
|
||||
5.2244898e+001
|
||||
1.2929293e+002
|
||||
1.2929293e+002
|
||||
1.5238095e+002
|
||||
1.5238095e+002
|
||||
1.3913043e+002
|
||||
9.0140845e+001
|
||||
1.0940171e+002
|
||||
9.0140845e+001
|
||||
1.2307692e+002
|
||||
8.9510490e+001
|
||||
6.9565217e+001
|
||||
7.3142857e+001
|
||||
1.1034483e+002
|
||||
7.8048780e+001
|
||||
7.2727273e+001
|
||||
1.0078740e+002
|
||||
1.0940171e+002
|
||||
1.1743119e+002
|
||||
8.7074830e+001
|
||||
1.8550725e+002
|
||||
6.5306122e+001
|
||||
1.3617021e+002
|
||||
5.2674897e+001
|
||||
1.0940171e+002
|
||||
1.5238095e+002
|
||||
1.4065934e+002
|
||||
1.0756303e+002
|
||||
1.0406504e+002
|
||||
5.0793651e+001
|
||||
4.9420849e+001
|
||||
4.4444444e+001
|
||||
7.0329670e+001
|
||||
7.2727273e+001
|
||||
7.4418605e+001
|
||||
1.1636364e+002
|
||||
1.0406504e+002
|
||||
1.2307692e+002
|
||||
1.2549020e+002
|
||||
1.7297297e+002
|
||||
4.5878136e+001
|
||||
4.9805447e+001
|
||||
6.2745098e+001
|
||||
9.2086331e+001
|
||||
9.1428571e+001
|
||||
5.7142857e+001
|
||||
4.8484848e+001
|
||||
4.1157556e+001
|
||||
2.2857143e+001
|
||||
3.0046948e+001
|
||||
9.4814815e+001
|
||||
5.7918552e+001
|
||||
9.0140845e+001
|
||||
7.4418605e+001
|
||||
7.4418605e+001
|
||||
5.4700855e+001
|
||||
9.5522388e+001
|
||||
7.4853801e+001
|
||||
9.4117647e+001
|
||||
9.5522388e+001
|
||||
9.9224806e+001
|
||||
8.1012658e+001
|
||||
1.1851852e+002
|
||||
6.8817204e+001
|
||||
8.5906040e+001
|
||||
6.7015707e+001
|
||||
4.3537415e+001
|
||||
6.5306122e+001
|
||||
3.1295844e+001
|
||||
7.5739645e+001
|
||||
6.2135922e+001
|
||||
9.9224806e+001
|
||||
5.7657658e+001
|
||||
5.2244898e+001
|
||||
5.8447489e+001
|
||||
0.0000000e+000
|
||||
0.0000000e+000
|
||||
0.0000000e+000
|
||||
0.0000000e+000
|
||||
0.0000000e+000
|
|
@ -1,23 +0,0 @@
|
|||
# Makefile for Portaudio test programs
|
||||
# Requires Portaudio V19
|
||||
|
||||
CFLAGS = -g -Wall -I../src
|
||||
LIBS = -lm -lportaudio -pthread
|
||||
SRC = ../src/fdmdv.c ../src/kiss_fft.c ../src/fifo.c
|
||||
|
||||
all: pa_rec pa_play pa_recplay pa_impresp
|
||||
|
||||
pa_rec: Makefile pa_rec.c $(SRC)
|
||||
gcc $(CFLAGS) pa_rec.c $(SRC) -o pa_rec $(LIBS)
|
||||
|
||||
pa_play: Makefile pa_play.c $(SRC)
|
||||
gcc $(CFLAGS) pa_play.c $(SRC) -o pa_play $(LIBS)
|
||||
|
||||
pa_recplay: Makefile pa_recplay.c $(SRC)
|
||||
gcc $(CFLAGS) pa_recplay.c $(SRC) -o pa_recplay $(LIBS)
|
||||
|
||||
pa_impresp: Makefile pa_impresp.c $(SRC)
|
||||
gcc $(CFLAGS) pa_impresp.c $(SRC) -o pa_impresp $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f pa_rec pa_play pa_recplay
|
|
@ -1,254 +0,0 @@
|
|||
/*
|
||||
pa_impresp.c
|
||||
David Rowe
|
||||
August 29 2012
|
||||
|
||||
Measures the impulse reponse of the path between the speaker and
|
||||
microphone. Used to explore why Codec audio quality is
|
||||
different through a speaker and headphones.
|
||||
|
||||
Modified from pa_playrec.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
#include "fdmdv.h"
|
||||
|
||||
#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 N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
|
||||
#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
|
||||
#define NUM_CHANNELS 2 /* I think most sound cards prefer
|
||||
stereo, we will convert to mono
|
||||
as we sample */
|
||||
|
||||
#define IMPULSE_AMP 16384 /* amplitide of impulse */
|
||||
#define IMPULSE_PERIOD 0.1 /* period (dly between impulses) in secs */
|
||||
|
||||
/* state information passed to call back */
|
||||
|
||||
typedef struct {
|
||||
float in48k[FDMDV_OS_TAPS + N48];
|
||||
float in8k[MEM8 + N8];
|
||||
FILE *fimp;
|
||||
float *impulse_buf;
|
||||
int impulse_buf_length;
|
||||
int impulse_sample_count;
|
||||
int framesLeft;
|
||||
} paTestData;
|
||||
|
||||
|
||||
/*
|
||||
This routine will be called by the PortAudio engine when audio is
|
||||
required. It may be called at interrupt level on some machines so
|
||||
don't do anything that could mess up the system like calling
|
||||
malloc() or free().
|
||||
*/
|
||||
|
||||
static int callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
int i;
|
||||
short *rptr = (short*)inputBuffer;
|
||||
short *wptr = (short*)outputBuffer;
|
||||
float *in8k = data->in8k;
|
||||
float *in48k = data->in48k;
|
||||
float out8k[N8];
|
||||
float out48k[N48];
|
||||
short out48k_short[N48];
|
||||
short out8k_short[N8];
|
||||
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
assert(inputBuffer != NULL);
|
||||
|
||||
/* just use left channel */
|
||||
|
||||
for(i=0; i<framesPerBuffer; i++,rptr+=2)
|
||||
data->in48k[i+FDMDV_OS_TAPS] = *rptr;
|
||||
|
||||
/* downsample and update filter memory */
|
||||
|
||||
fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
in48k[i] = in48k[i+framesPerBuffer];
|
||||
|
||||
/* write impulse response to disk */
|
||||
|
||||
for(i=0; i<N8; i++)
|
||||
out8k_short[i] = out8k[i];
|
||||
fwrite(out8k_short, sizeof(short), N8, data->fimp);
|
||||
|
||||
/* play side, read from impulse buffer */
|
||||
|
||||
for(i=0; i<N8; i++) {
|
||||
in8k[MEM8+i] = data->impulse_buf[data->impulse_sample_count];
|
||||
data->impulse_sample_count++;
|
||||
if (data->impulse_sample_count == data->impulse_buf_length)
|
||||
data->impulse_sample_count = 0;
|
||||
}
|
||||
|
||||
/* upsample and update filter memory */
|
||||
|
||||
fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
|
||||
for(i=0; i<MEM8; i++)
|
||||
in8k[i] = in8k[i+N8];
|
||||
|
||||
assert(outputBuffer != NULL);
|
||||
|
||||
/* write signal to both channels */
|
||||
|
||||
for(i=0; i<N48; i++)
|
||||
out48k_short[i] = (short)out48k[i];
|
||||
for(i=0; i<framesPerBuffer; i++,wptr+=2) {
|
||||
wptr[0] = out48k_short[i];
|
||||
wptr[1] = out48k_short[i];
|
||||
}
|
||||
|
||||
data->framesLeft -= framesPerBuffer;
|
||||
if (data->framesLeft > 0)
|
||||
return paContinue;
|
||||
else
|
||||
return paComplete;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
PaStream* stream;
|
||||
PaError err = paNoError;
|
||||
paTestData data;
|
||||
int i, numSecs;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("usage: %s impulseRawFile time(s)\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
data.fimp = fopen(argv[1], "wb");
|
||||
if (data.fimp == NULL) {
|
||||
printf("Error opening impulse output file %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
numSecs = atoi(argv[2]);
|
||||
data.framesLeft = numSecs * SAMPLE_RATE;
|
||||
|
||||
/* init filter states */
|
||||
|
||||
for(i=0; i<MEM8; i++)
|
||||
data.in8k[i] = 0.0;
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
data.in48k[i] = 0.0;
|
||||
|
||||
/* init imupulse */
|
||||
|
||||
data.impulse_buf_length = IMPULSE_PERIOD*(SAMPLE_RATE/FDMDV_OS);
|
||||
printf("%d\n",data.impulse_buf_length);
|
||||
data.impulse_buf = (float*)malloc(data.impulse_buf_length*sizeof(float));
|
||||
assert(data.impulse_buf != NULL);
|
||||
data.impulse_buf[0] = IMPULSE_AMP;
|
||||
for(i=1; i<data.impulse_buf_length; i++)
|
||||
data.impulse_buf[i] = 0;
|
||||
data.impulse_sample_count = 0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
if (inputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default input device.\n");
|
||||
goto done;
|
||||
}
|
||||
inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
|
||||
inputParameters.sampleFormat = paInt16;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
if (outputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default output device.\n");
|
||||
goto done;
|
||||
}
|
||||
outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Play some audio --------------------------------------------- */
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
N48,
|
||||
paClipOff,
|
||||
callback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
Pa_Sleep(100);
|
||||
}
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
|
||||
fclose(data.fimp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
/*
|
||||
pa_play.c
|
||||
David Rowe
|
||||
July 8 2012
|
||||
|
||||
Converts samples from a 16 bit short 8000 Hz rawfile to 480000Hz
|
||||
sample rate and plays them using the default sound device. Used as
|
||||
an intermediate step in Portaudio integration.
|
||||
|
||||
Modified from paex_record.c Portaudio example. Original author
|
||||
author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
#include "fdmdv.h"
|
||||
|
||||
#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 N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
|
||||
#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
|
||||
#define NUM_CHANNELS 2 /* I think most sound cards prefer
|
||||
stereo, we will convert to mono
|
||||
as we sample */
|
||||
|
||||
/* state information passed to call back */
|
||||
|
||||
typedef struct {
|
||||
FILE *fin;
|
||||
float in8k[MEM8 + N8];
|
||||
} paTestData;
|
||||
|
||||
|
||||
/*
|
||||
This routine will be called by the PortAudio engine when audio is
|
||||
required. It may be called at interrupt level on some machines so
|
||||
don't do anything that could mess up the system like calling
|
||||
malloc() or free().
|
||||
*/
|
||||
|
||||
static int playCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
FILE *fin = data->fin;
|
||||
int i, nread;
|
||||
int finished;
|
||||
short *wptr = (short*)outputBuffer;
|
||||
float *in8k = data->in8k;
|
||||
float out48k[N48];
|
||||
short out48k_short[N48];
|
||||
short in8k_short[N8];
|
||||
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
(void) userData;
|
||||
|
||||
/* note Portaudio docs recs. against making systems calls like
|
||||
fwrite() in this callback but seems to work OK */
|
||||
|
||||
nread = fread(in8k_short, sizeof(short), N8, fin);
|
||||
if (nread == N8)
|
||||
finished = paContinue;
|
||||
else
|
||||
finished = paComplete;
|
||||
|
||||
for(i=0; i<N8; i++)
|
||||
in8k[MEM8+i] = in8k_short[i];
|
||||
|
||||
/* upsample and update filter memory */
|
||||
|
||||
fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
|
||||
for(i=0; i<MEM8; i++)
|
||||
in8k[i] = in8k[i+N8];
|
||||
|
||||
assert(outputBuffer != NULL);
|
||||
|
||||
/* write signal to both channels */
|
||||
|
||||
for(i=0; i<N48; i++)
|
||||
out48k_short[i] = (short)out48k[i];
|
||||
for(i=0; i<framesPerBuffer; i++,wptr+=2) {
|
||||
wptr[0] = out48k_short[i];
|
||||
wptr[1] = out48k_short[i];
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream* stream;
|
||||
PaError err = paNoError;
|
||||
paTestData data;
|
||||
int i;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("usage: %s rawFile\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
data.fin = fopen(argv[1], "rt");
|
||||
if (data.fin == NULL) {
|
||||
printf("Error opening input raw file %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0; i<MEM8; i++)
|
||||
data.in8k[i] = 0.0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default input device */
|
||||
if (outputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default output device.\n");
|
||||
goto done;
|
||||
}
|
||||
outputParameters.channelCount = NUM_CHANNELS; /* stereo input */
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Play some audio --------------------------------------------- */
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
NULL,
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
N48,
|
||||
paClipOff,
|
||||
playCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
Pa_Sleep(100);
|
||||
}
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
fclose(data.fin);
|
||||
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
pa_rec.c
|
||||
David Rowe
|
||||
July 6 2012
|
||||
|
||||
Records at 48000 Hz from default sound device, convertes to 8 kHz,
|
||||
and saves to raw file. Used to get experience with Portaudio.
|
||||
|
||||
Modified from paex_record.c Portaudio example. Original author
|
||||
author Phil Burk http://www.softsynth.com
|
||||
|
||||
To Build:
|
||||
|
||||
gcc paex_rec.c -o paex_rec -lm -lrt -lportaudio -pthread
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
#include "fdmdv.h"
|
||||
|
||||
#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 N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
|
||||
#define NUM_CHANNELS 2 /* I think most sound cards prefer
|
||||
stereo, we will convert to mono
|
||||
as we sample */
|
||||
|
||||
/* state information passed to call back */
|
||||
|
||||
typedef struct {
|
||||
FILE *fout;
|
||||
int framesLeft;
|
||||
float in48k[FDMDV_OS_TAPS + N48];
|
||||
} paTestData;
|
||||
|
||||
|
||||
/*
|
||||
This routine will be called by the PortAudio engine when audio is
|
||||
available. It may be called at interrupt level on some machines so
|
||||
don't do anything that could mess up the system like calling
|
||||
malloc() or free().
|
||||
*/
|
||||
|
||||
static int recordCallback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
FILE *fout = data->fout;
|
||||
int framesToCopy;
|
||||
int i;
|
||||
int finished;
|
||||
short *rptr = (short*)inputBuffer;
|
||||
float out8k[N8];
|
||||
short out8k_short[N8];
|
||||
|
||||
(void) outputBuffer; /* Prevent unused variable warnings. */
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
(void) userData;
|
||||
|
||||
if (data->framesLeft < framesPerBuffer) {
|
||||
framesToCopy = data->framesLeft;
|
||||
finished = paComplete;
|
||||
}
|
||||
else {
|
||||
framesToCopy = framesPerBuffer;
|
||||
finished = paContinue;
|
||||
}
|
||||
data->framesLeft -= framesToCopy;
|
||||
|
||||
assert(inputBuffer != NULL);
|
||||
|
||||
/* just use left channel */
|
||||
|
||||
for(i=0; i<framesToCopy; i++,rptr+=2)
|
||||
data->in48k[i+FDMDV_OS_TAPS] = *rptr;
|
||||
|
||||
/* downsample and update filter memory */
|
||||
|
||||
fdmdv_48_to_8(out8k, &data->in48k[FDMDV_OS_TAPS], N8);
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
data->in48k[i] = data->in48k[i+framesToCopy];
|
||||
|
||||
/* save 8k to disk */
|
||||
|
||||
for(i=0; i<N8; i++)
|
||||
out8k_short[i] = (short)out8k[i];
|
||||
|
||||
/* note Portaudio docs recs. against making systems calls like
|
||||
fwrite() in this callback but seems to work OK */
|
||||
|
||||
fwrite(out8k_short, sizeof(short), N8, fout);
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PaStreamParameters inputParameters;
|
||||
PaStream* stream;
|
||||
PaError err = paNoError;
|
||||
paTestData data;
|
||||
int i;
|
||||
int numSecs;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("usage: %s rawFile time(s)\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
data.fout = fopen(argv[1], "wt");
|
||||
if (data.fout == NULL) {
|
||||
printf("Error opening output raw file %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
numSecs = atoi(argv[2]);
|
||||
data.framesLeft = numSecs * SAMPLE_RATE;
|
||||
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
data.in48k[i] = 0.0;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n",
|
||||
Pa_GetVersion(), Pa_GetVersionText() );
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
if (inputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default input device.\n");
|
||||
goto done;
|
||||
}
|
||||
inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
|
||||
inputParameters.sampleFormat = paInt16;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Record some audio --------------------------------------------- */
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
NULL, /* &outputParameters, */
|
||||
SAMPLE_RATE,
|
||||
N48,
|
||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||
recordCallback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
Pa_Sleep(100);
|
||||
}
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
fclose(data.fout);
|
||||
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
pa_recplay.c
|
||||
David Rowe
|
||||
July 8 2012
|
||||
|
||||
Echos audio from sound card input to sound card output. Samples at
|
||||
48 kHz, converts to 8 kHz, converts back to 48kHz, and plays using
|
||||
the default sound device. Used as an intermediate step in
|
||||
Portaudio integration.
|
||||
|
||||
Modified from paex_record.c Portaudio example. Original author
|
||||
author Phil Burk http://www.softsynth.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "portaudio.h"
|
||||
#include "fdmdv.h"
|
||||
#include "fifo.h"
|
||||
|
||||
#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 N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
|
||||
#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
|
||||
#define NUM_CHANNELS 2 /* I think most sound cards prefer
|
||||
stereo, we will convert to mono
|
||||
as we sample */
|
||||
#define MAX_FPB 2048 /* maximum value of framesPerBuffer */
|
||||
|
||||
/* state information passed to call back */
|
||||
|
||||
typedef struct {
|
||||
float in48k[FDMDV_OS_TAPS + N48];
|
||||
float in8k[MEM8 + N8];
|
||||
struct FIFO *infifo;
|
||||
struct FIFO *outfifo;
|
||||
} paTestData;
|
||||
|
||||
|
||||
/*
|
||||
This routine will be called by the PortAudio engine when audio is
|
||||
required. It may be called at interrupt level on some machines so
|
||||
don't do anything that could mess up the system like calling
|
||||
malloc() or free().
|
||||
*/
|
||||
|
||||
static int callback( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
paTestData *data = (paTestData*)userData;
|
||||
int i;
|
||||
short *rptr = (short*)inputBuffer;
|
||||
short *wptr = (short*)outputBuffer;
|
||||
float *in8k = data->in8k;
|
||||
float *in48k = data->in48k;
|
||||
float out8k[N8];
|
||||
float out48k[N48];
|
||||
short out48k_short[N48];
|
||||
short in48k_short[N48];
|
||||
short indata[MAX_FPB];
|
||||
short outdata[MAX_FPB];
|
||||
|
||||
(void) timeInfo;
|
||||
(void) statusFlags;
|
||||
|
||||
assert(inputBuffer != NULL);
|
||||
assert(outputBuffer != NULL);
|
||||
|
||||
/*
|
||||
framesPerBuffer is portaudio-speak for number of samples we
|
||||
actually get from the record side and need to provide to the
|
||||
play side. On Linux (at least) it was found that
|
||||
framesPerBuffer may not always be what we ask for in the
|
||||
framesPerBuffer field of Pa_OpenStream. For example a request
|
||||
for 960 sample buffers lead to framesPerBuffer = 1024.
|
||||
|
||||
To perform the 48 to 8 kHz conversion we need an integer
|
||||
multiple of FDMDV_OS samples to support the interpolation and
|
||||
decimation. As we can't guarantee the size of framesPerBuffer
|
||||
we do a little FIFO buffering.
|
||||
*/
|
||||
|
||||
//printf("framesPerBuffer: %d N48 %d\n", framesPerBuffer, N48);
|
||||
|
||||
/* assemble a mono buffer (just use left channel) and write to FIFO */
|
||||
|
||||
assert(framesPerBuffer < MAX_FPB);
|
||||
for(i=0; i<framesPerBuffer; i++,rptr+=2)
|
||||
indata[i] = *rptr;
|
||||
fifo_write(data->infifo, indata, framesPerBuffer);
|
||||
|
||||
/* while we have enough samples available ... */
|
||||
|
||||
//printf("infifo before: %d\n", fifo_n(data->infifo));
|
||||
while (fifo_read(data->infifo, in48k_short, N48) == 0) {
|
||||
|
||||
/* convert to float */
|
||||
|
||||
for(i=0; i<N48; i++)
|
||||
in48k[FDMDV_OS_TAPS + i] = in48k_short[i];
|
||||
|
||||
/* downsample and update filter memory */
|
||||
|
||||
fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
in48k[i] = in48k[i+N48];
|
||||
|
||||
/* play side, back up to 8k */
|
||||
|
||||
for(i=0; i<N8; i++)
|
||||
in8k[MEM8+i] = out8k[i];
|
||||
|
||||
/* upsample and update filter memory */
|
||||
|
||||
fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
|
||||
for(i=0; i<MEM8; i++)
|
||||
in8k[i] = in8k[i+N8];
|
||||
|
||||
/* write signal to both channels */
|
||||
|
||||
for(i=0; i<N48; i++)
|
||||
out48k_short[i] = (short)out48k[i];
|
||||
|
||||
fifo_write(data->outfifo, out48k_short, N48);
|
||||
}
|
||||
//printf("infifo after: %d\n", fifo_n(data->infifo));
|
||||
//printf("outfifo : %d\n", fifo_n(data->outfifo));
|
||||
|
||||
|
||||
/* OK now set up output samples */
|
||||
|
||||
if (fifo_read(data->outfifo, outdata, framesPerBuffer) == 0) {
|
||||
|
||||
/* write signal to both channels */
|
||||
|
||||
for(i=0; i<framesPerBuffer; i++,wptr+=2) {
|
||||
wptr[0] = outdata[i];
|
||||
wptr[1] = outdata[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf("no data\n");
|
||||
/* zero output if no data available */
|
||||
for(i=0; i<framesPerBuffer; i++,wptr+=2) {
|
||||
wptr[0] = 0;
|
||||
wptr[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PaStreamParameters inputParameters, outputParameters;
|
||||
PaStream* stream;
|
||||
PaError err = paNoError;
|
||||
paTestData data;
|
||||
int i;
|
||||
|
||||
/* init callback data */
|
||||
|
||||
for(i=0; i<MEM8; i++)
|
||||
data.in8k[i] = 0.0;
|
||||
for(i=0; i<FDMDV_OS_TAPS; i++)
|
||||
data.in48k[i] = 0.0;
|
||||
|
||||
data.infifo = fifo_create(2*N48);
|
||||
data.outfifo = fifo_create(2*N48);
|
||||
|
||||
/* init port audio */
|
||||
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
|
||||
if (inputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default input device.\n");
|
||||
goto done;
|
||||
}
|
||||
inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
|
||||
inputParameters.sampleFormat = paInt16;
|
||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||
if (outputParameters.device == paNoDevice) {
|
||||
fprintf(stderr,"Error: No default output device.\n");
|
||||
goto done;
|
||||
}
|
||||
outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
/* Play some audio --------------------------------------------- */
|
||||
|
||||
err = Pa_OpenStream(
|
||||
&stream,
|
||||
&inputParameters,
|
||||
&outputParameters,
|
||||
SAMPLE_RATE,
|
||||
512,
|
||||
paClipOff,
|
||||
callback,
|
||||
&data );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
err = Pa_StartStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
|
||||
{
|
||||
Pa_Sleep(100);
|
||||
}
|
||||
if( err < 0 ) goto done;
|
||||
|
||||
err = Pa_CloseStream( stream );
|
||||
if( err != paNoError ) goto done;
|
||||
|
||||
|
||||
done:
|
||||
Pa_Terminate();
|
||||
if( err != paNoError )
|
||||
{
|
||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||
fprintf( stderr, "Error number: %d\n", err );
|
||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||
err = 1; /* Always return 0 or 1, but no other return codes. */
|
||||
}
|
||||
|
||||
fifo_destroy(data.infifo);
|
||||
fifo_destroy(data.outfifo);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue