Full Code of idirect3d/lakey for AI

master 9ae57ee0b6fe cached
74 files
337.5 KB
116.4k tokens
197 symbols
1 requests
Download .txt
Showing preview only (380K chars total). Download the full file or copy to clipboard to get everything.
Repository: idirect3d/lakey
Branch: master
Commit: 9ae57ee0b6fe
Files: 74
Total size: 337.5 KB

Directory structure:
gitextract_rhtqzxy4/

├── .project
├── LICENSE
├── README.md
├── bin/
│   ├── Lakey.v2.1.build.0019.Pencil/
│   │   ├── WINIO.VXD
│   │   ├── WinIo.sys
│   │   ├── lakey.ini
│   │   └── lakey_ZH.ini
│   └── Lakey.v2.2.build.0020.Paper/
│       ├── WINIO.VXD
│       └── WinIo.sys
├── doc/
│   └── index.html
└── src/
    ├── CommFunc.cpp
    ├── CommFunc.h
    ├── EventListener.cpp
    ├── EventListener.h
    ├── EventManagerWin32.cpp
    ├── EventManagerWin32.h
    ├── FFT.cpp
    ├── FFT.h
    ├── Graphics.cpp
    ├── Graphics.h
    ├── LaButton.cpp
    ├── LaButton.h
    ├── LaHwControl.cpp
    ├── LaHwControl.h
    ├── LaJournalPanel.cpp
    ├── LaJournalPanel.h
    ├── LaLabel.cpp
    ├── LaLabel.h
    ├── LaLine.cpp
    ├── LaLine.h
    ├── LaNetwork.cpp
    ├── LaNetwork.h
    ├── LaSpectrogram.cpp
    ├── LaSpectrogram.h
    ├── LaTuner.cpp
    ├── LaTuner.h
    ├── LaWaveCapture.cpp
    ├── LaWaveCapture.h
    ├── LaWaveFile.cpp
    ├── LaWaveFile.h
    ├── Lakey.aps
    ├── Lakey.h
    ├── Lakey.rc
    ├── Lakey.sln
    ├── Lakey.vcproj
    ├── Lakey.vcxproj
    ├── Lakey.vcxproj.filters
    ├── Lakey.vcxproj.user
    ├── LakeyMain.cpp
    ├── LakeyMainWindow.cpp
    ├── LakeyMainWindow.h
    ├── LakeySetting.cpp
    ├── LakeySetting.h
    ├── MorseParser.cpp
    ├── MorseParser.h
    ├── ReadMe.txt
    ├── Resource.h
    ├── SinSound.cpp
    ├── SinSound.h
    ├── UpgradeLog.XML
    ├── UpgradeLog2.XML
    ├── UpgradeLog3.XML
    ├── WINIO.VXD
    ├── WinIo.sys
    ├── html1.htm
    ├── lakey.ini
    ├── lakey_EN.ini
    ├── lakey_ZH.ini
    ├── mc.txt
    ├── mytest.cpp
    ├── mytest.h
    ├── resource.h
    ├── stdafx.cpp
    └── stdafx.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>lakey</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
	</natures>
</projectDescription>


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, 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
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU 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
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state 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 program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
# lakey
Lakey, a CW training tool.

Lakey是一款摩尔斯电码发报练习软件,具有摩尔斯电码解析、音频频谱分析、摩尔斯电码听抄练习、可进行多主机网络通联练习或试验等特点。

![photo](./doc/images/img21.png)

常见问题临时解决方案:
如果在Win7、Win8、Win10及以后版本的Windows上,包括32位和64位系统,遇到打开报错的问题,可以尝试检查是否打开了音频输入设备,一般插一个麦克风就好了。

制作思想:
- 简单至上,开箱即用,无需设置,简单直观。
- 最小依赖,仅依赖操作系统自带库。
- 短小精悍,体量仅200多KB。
- 共同进步,完全开源。

主要特性:

- 利用键盘或鼠标进行摩尔斯电码发报练习,支持键盘直接录入,支持手键和自动键方式;
- 摩尔斯电码听抄练习,可以将听抄音频转换为WAV文件,用于通过手机或其他移动设备进行听抄练习;
- 摩尔斯电码解析,可以用做发报练习参考;
- 音频频谱分析,可以对电脑音频模拟输入(Line in、Aux in或Mic in等)进行音频分析并显示;
- 发报键状态可以输出到计算机I/O接口,对外围设备进行简单控制;
- 可进行多主机网络通联练习或试验。

本软件的目标是设计成一个使用简便,能够尽量利用一般PC本身具有的硬件功能和性能(主要指CPU的运算和声卡的音频捕捉/播放能力), 实现不用另接特殊外围接口电路,不用改/加装电键等,即可让PC具有摩尔斯电码(Morse Code)的收发能力软件。未来可逐渐通过对PC硬件性能的挖掘, 实现对音频信号进行分析、过滤、处理。

从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号。 如2.0版本被赋予Zongzi(粽子)这个代号。但应该说明,Lakey项目本身将继续立足于实验目的,因此作者并不保证所有功能都是完美可用的, 即所有版本可能都带有BETA测试版本的意味,这点请大家使用时务必注意。 同时希望大家继续多提意见,帮助作者不断完善Lakey。这点在对以往版本的改进过程中已经被证实是最为重要的手段。在此感谢所有提出过意见或建议的朋友们!


================================================
FILE: bin/Lakey.v2.1.build.0019.Pencil/lakey.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=93,18,1013,454
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,Pause,Continue
sendfile=500,265,91,16,0075,File...
autokeyswitch=706,265,91,16,0009,Manual,Auto(L/R),Auto(R/L)
noiseswitch=809,265,91,16,0076,Disturb
sendvol=500,168,90,90,-80.000000,0.000000,0.000000,Volumn(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,Disturb(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,Speed(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,1.875000,Spectrogram(dB)
[KOCH]
charlist=
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0


================================================
FILE: bin/Lakey.v2.1.build.0019.Pencil/lakey_ZH.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=224,104,1144,540
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,ͣ,
sendfile=500,265,91,16,0075,ļ...
autokeyswitch=706,265,91,16,0009,ֶ,Զ(/),Զ(/)
noiseswitch=809,265,91,16,0076,
sendvol=500,168,90,90,-80.000000,0.000000,-15.312500,(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,ٶ(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,55.781250,Ƶ(dB)
[KOCH]
charlist=KMRSUAPTLOWI.NJEF0Y,VG5/Q9ZH38B?427C1D6X
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
)=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0


================================================
FILE: doc/index.html
================================================
<html>
<head>
<meta http-equiv=content-type content="text/html; charset=utf-8">
<title>Lakey 2.1 Pencil (Build 0019) - CW/摩尔斯码/发报/收报/练习/音频分析/联网(CW, Morse code, Sending, Receiving, Training, Analyzing, Networking)</title>
<style> 
	body { font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; }
	p { text-indent: 20pt; font-size: 10pt; }
	li { font-size: 10pt; }
	.comment { border: #000000 1px solid; font-size: 9pt; margin: 18pt; }
	h2 { color: #000090; }
	h3 { color: #505080; }
</style>
</head>
<body>
<h1>Lakey 2.1 Pencil (Build 0019) - 使用手册</h1>
<h5>CW/摩尔斯码/发报/收报/练习/音频分析/联网</h5>
<hr>
<h5 style="color: red">永久开源、免费!</h5>
<h5>最新下载(2012/6/30): </h5>
<p style="color: blue">[<a href="http://www.layala.org/lakey/download/Lakey.v2.1.build.0019.Pencil.bin.zip">运行程序</a>]
	[<a href="http://www.layala.org/lakey/download/Lakey.v2.1.build.0019.Pencil.man.zip">使用手册</a>]
	[<a href="http://www.layala.org/lakey/download/Lakey.v2.1.build.0019.Pencil.src.zip">源代码</a>]</p>
<br>
<br>
<br>
<img src="images/logo.jpg" alt="Lakey's logo">
<br>
<br>
<br>
<br>
<h5>版本:	2.1.0019(Pencil)</h5>
<h5>作者:	BG1VLZ</h5>
<h5>E-Mail/MSN: <a href="mailto:idirect3d@hotmail.com">idirect3d@hotmail.com(非常希望能得到您的使用反馈, 谢谢!)</a></h5>

<hr>
<h2>目录</h2>
<ul>
	<li><a href="#topic1">写在最前</a></li>
	<li><a href="#topic2">功能简介</a></li>
	<li><a href="#topic3">收报</a></li>
  <ul>
    <li><a href="#topic31">有趣的频谱</a></li>
  </ul>
    <li><a href="#topic4">发报</a></li>
	<ul>
		<li><a href="#topic41a">手动键发报</a></li>
		<li><a href="#topic41b">自动键发报</a></li>
		<li><a href="#topic42">字符发报</a></li>
		<li><a href="#topic43">文件发报</a></li>
		<li><a href="#topic44">与发信机的连接</a></li>
		<li><a href="#topic45">发送暂停</a></li>
	</ul>
	<li><a href="#topic4a">网络通联</a></li>
	<li><a href="#topic5">参数调整</a></li>
	<ul>
		<li><a href="#topic51">CW规则</a></li>
		<li><a href="#topic52">发送</a></li>
		<li><a href="#topic53">接收</a></li>
		<li><a href="#topic54">练习</a></li>
		<li><a href="#topic55">网络</a></li>
		<li><a href="#topic56">I/O</a></li>
		<li><a href="#topic58">参数调整失败怎么办?</a></li>
	</ul>
	<li><a href="#topic8">练习</a></li>
	<ul>
		<li><a href="#topic81">开始进行Koch模式练习</a></li>
		<li><a href="#topic83">生成抄报练习音频文件</a></li>
		<li><a href="#topic85">发报练习</a></li>
	</ul>
	<li><a href="#topic8a">CW练习技巧</a></li>
	<ul>
		<li><a href="#topic8a1">古典练习法</a></li>
		<li><a href="#topic8a2">Koch练习法</a></li>
		<li><a href="#topic8a3">Farnsworth练习法</a></li>
	</ul>
	<li><a href="#topic6">系统需求</a></li>
	<li><a href="#topic7">版本更新历史</a></li>
</ul>
<hr>
<h2><a name="topic1">写在最前</a></h2>
 
<p>Lakey这是一个多功能且完全免费的CW练习/收/发软件,供大家学习研究,有需要源码的朋友可以访问Lakey的主页<a href="www.lakey.cn">www.lakey.cn</a>下载
(目前原域名: www.layala.org将继续使用), 
由于该主机使用动态DNS访问一台非固定IP主机, 并不能保证100% 7x24小时运行, 如果不能下载, 请给我发邮件或加为MSN索取(idirect3d@hotmail.com)。
不便之处望朋友们谅解。在未来,我会不断改进其功能和修正错误。</p>

  <p>最新的开发进展</p>
  <p>v2.1(Pencil)</p>
  <p>(1)实现了由BA3CE建议的发送练习功能,并能够将练习时发送的文本记录下来;</p>
  <p>(2)新增加的频谱显示将频率坐标轴方向反向,即频率较低的数据显示在靠下的位置;</p>
<br>
  <p>v2.0(Zongzi)</p>
  <p>(1)响应众多HAM朋友的意见,同时也是对过去Lakey功能缺陷的弥补,修正了自动键功能(感谢BG8ST及其他提出了此问题但没有留下呼号的朋友);</p>
  <p>(2)修正了“/”符号的Morse编码错误(感谢BD1GXH);</p>
  <p>(3)引入FFT算法;</p>
  <p>(4)增加了频率域与时间域相结合的频谱分析显示功能。应该说,此功能是本次Lakey的最大功能升级。
  它可以将混杂在实际嘈杂电波中的CW信号明显的“标记”出来,从而帮助接受者通过眼睛来识别Morse编码。
  该功能的灵感来源于Foobar2000这款音乐播放软件的频谱分析功能。</p>
 
 
<p>本软件的目标是设计成一个使用简便,能够尽量利用一般PC本身具有的硬件功能和性能(主要指CPU的运算和声卡的音频捕捉/播放能力),
实现不用另接特殊外围接口电路,不用改/加装电键等,即可让PC具有摩尔斯电码(Morse Code)的收发能力软件。未来可逐渐通过对PC硬件性能的挖掘,
实现对音频信号进行分析、过滤、处理。</p>
 
<p>从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号。
如2.0版本被赋予Zongzi(粽子)这个代号。但应该说明,Lakey项目本身将继续立足于实验目的,因此作者并不保证所有功能都是完美可用的,
即所有版本可能都带有BETA测试版本的意味,这点请大家使用时务必注意。
同时希望大家继续多提意见,帮助作者不断完善Lakey。这点在对以往版本的改进过程中已经被证实是最为重要的手段。在此感谢所有提出过意见或建议的朋友们!</p>
 
<hr>
<h2><a name="topic2">功能简介</a></h2>
 
<p>支持虚拟自动键和手键发送方式。</p>

<p>支持多台计算机通过网络,实时进行CW通联和练习。</p>

<p>支持对音频信号的频率域、时间域的单独和组合分析显示。</p>
 
<p>利用PC声卡的音频捕捉播放功能,实现摩尔斯电码的收/发。收报时可自动实现摩尔斯电码到字母/数字的翻译转换;
发报时可以选择采用手工CW或者直接键入字母/数字两种方式。</p>
 
<p>手工方式可以使用键盘按键或者鼠标按键作为电键。也就是说,一台电脑通过普通音频连接线连接到普通发射/接收设备即可实现CW通信或练习。</p>
 
<p>通过并口、串口或其它以I/O地址寻址的计算机接口,实现了对外部发信机的简单发射控制。</p>
 
<p>生成任意抄报练习音频文件,可以放到手机等便携设备方便随时练习。</p>

<p>支持发送练习。</p>
 
<p>软件界面从上到下大体分为4部分,如下图所示:</p>

<h5>英文模式(缺省)</h5>
<img src="images/img21.png" alt="Lakey英文界面">

<h5>中文模式(使用Lakey_zh.ini)</h5>
<img src="images/img22.png" alt="Lakey中文界面">

<p>
    后面章节将对这些部分分别介绍。以上两种界面模式,可通过将不同.ini文件复制为Lakey.ini文件来实现。</p>
 
<hr>
<h2><a name="topic3">收报</a></h2>
 
<p>首先要把收信机的音频输出接到PC的音频输入口,如:Line in, Aux in, CD audio in等等。由于软件使用单声道处理,而一般这些接口都为双声道,因此最好将两个声道并联后接收信机的单声道输出。</p>
<p>将操作系统的录音来源选择为接入的接口,如果来源选择不对将不能实现收报的摩尔斯码翻译。Windows的录音来源可进入[控制面板->声音和音频设备]中进行选择,如下图:</p>
<img src="images/img31.jpg">
<p><b>在上面的窗口中点击录音栏中的[音量…]按钮</b></p>
 
<img src="images/img32.jpg">
<p><b>在这里选择接入接收机音频输出信号的接口</b></p>
<p>完成上面的步骤,就可以收报了。收报信息中包括输入音频的波形、简单频谱分析、CW点记录和翻译后的的字符。
	使用鼠标左键和右键点击频谱分析控件可以分别改变波形幅度和频谱分析坐标系(线性/对数)。</p>
<p>要注意的是,在录音控制界面中,应尽量调整输入接口的电平,使软件显示的波形振幅尽量大且没有削波失真。</p>

  <h3><a name="topic31">有趣的频谱</a></h3>
  <p>从Lakey2.0版本(Zongzi)开始,新增加了结合频率、时间、分布能量显示的综合频谱图。
  这个功能,可以帮助收报者,从嘈杂的无线电环境中发现和辨别有规律CW信号。</p>
  <p>在Lakey界面右上方新增加的这个频谱图形中,横轴为时间域(不断滚动),纵轴为频率域(CW“音频”波长),
  某一点的亮度为某一时刻某一频点的振幅(可以理解音量或者能量)。
  这里需要注意的是,在靠下方显示的是收信机输出音频频率较低的信号。</p>
  <p>同一个电台的CW信号通过收信机输出后的音频信号,一般为一个固定频率,
  在频谱显示时一般会体现在一条直线上。因此使用者可以通过寻找同一水平线上有规律的间断线段来识别一个电台。
  而通过不同水平线也可以用来区分不同电台的信号。</p>
  <p>使用者可通过调节频谱增益旋钮(Spectrogram)来调节频率显示增益(亮度),以实现最佳的显示效果</p>
  <p>这里需要提醒使用者的是,实际的显示和使用效果,
  与收信机接收信号质量/输出电平、计算机的录音端口增益设置、Lakey的采样数量设置(设置页面)、
  Lakey的频谱增益设置(主界面Spectrogram旋钮)等都有直接或关联的关系,
  组合调整这些设置使信号与背景噪音能够获得一个比较好的显示对比度,让收报者能够比较容易的辨别CW信号,
  这通常需要充分利用收信机、计算机声卡以及数字处理程序的动态范围。
  而这也许需要一点点耐心。</p>
  <p>在未来,Lakey会不断完善频谱分析功能,适时推出计算机自动识别CW信号功能,甚至有可能实现多电台的自动识别和自动应答。
  如果您在这方面有好的想法,可以联系我,作者在此先表示感谢!</p>
 
<hr>
<h2><a name="topic4">发报</a></h2>

<h5>发报主要分以下四种方式:</h5>
<h3><a name="topic41a">手键发报(Manual)</a></h3>
<p>首先需要点击发送模式按钮,调整到“Manual”模式(缺省),然后使用鼠标键点击“CW”按钮模拟手键发报,也可以使用键盘中的[Enter]键模拟手键发报。Lakey在按下按键时会发出声音,抬起时关闭声音,同时会在发送窗口显示键击记录,并试图用摩尔斯电码翻译为字符、数字或标点。不能翻译的部分显示为‘#’。</p>

 
<h3><a name="topic41b">自动键发报(Auto)</a></h3>
<p>首先需要点击发送模式按钮,调整到“Auto”模式,然后使用鼠标左/右键点击“CW”按钮模拟自动键发报。自动键有L/R和R/L两种模式(di/da),可以按照使用者习惯进行调整。与手动键一样,Lakey会对发送的信号进行翻译。</p>
 
<h3><a name="topic42">字符发报</a></h3>
<p>直接敲击键盘上的字母或数字键,系统将自动把键入的信息转换成摩尔斯电码,并输出到发送队列;同时,在发报信息的最下部会显示这个发送队列。</p>
<div class="comment">
注:发送队列是一个字符/数字队列,存放待发送的内容。发送队列长度为8192个字符,在队列满以后输入的字符将被舍弃。	
</div>
 
<h3><a name="topic43">文件发报</a></h3>
<p>点击[File…]按钮,打开一个要发送的文件。系统将把打开文件中符合摩尔斯电码的字符内容发送到4.2中介绍的发送队列。</p>
 
<h5>其他关于发报的主题:</h5>
 
<h3><a name="topic44">与发信机的连接</a></h3>
 
<h5>音频连接方式</h5>
 
<p>这种方式适用于当使用非CW方式发射模式时,如使用FM方式搭载摩尔斯音频信号的方式。现在在U/V段已经有利用这种方式进行摩尔斯收发练习的HAM,如北京的144.650MHz。</p>
 
<p>如果需要将音频摩尔斯电码发送到发信机,只需将PC的音频输出接到发信机的音频输入端口即可。</p>
 
<div class="comment">注意,对于多声道声卡来说,应该将前主声道(左或右)的信号接到发信机的音频输入端。</div>
 
<h5>并口连接方式</h5>
 
<p>这种方式适用于当使用标准CW方式发射模式时。当使用鼠标、键盘进行击发,或者键盘字符输入、文本文件输入时,通过并口的某一个针脚的电平来控制CW发信机起停,从而代替传统电键进行CW发射。其中,并口输出针脚电平规则可以通过设置界面随意调整。祥见:<a href="Topic54.htm">端口控制</a></p>
 
<div class="comment">注意,计算机的并口输出电平,在没有应用程序进行控制时,其电平状态有可能是随机的;因此,如果希望使用电脑通过并口控制发信机,保险起见,应当首先启动本应用程序,再连接或打开发信机。</div>
 
<p>并口具体针脚定义如下:</p>
<table>
	<tr><td>针脚序号</td><td>说明</td></tr>
	<tr><td>1</td><td>STROBE 选通</td></tr>
	<tr><td>2-9</td><td>DATA0-DATA7 数据0-7</td></tr>
	<tr><td>10</td><td>ACKNLG 确认</td></tr>
	<tr><td>11</td><td>BUSY 忙</td></tr>
	<tr><td>12</td><td>PE 缺纸</td></tr>
	<tr><td>13</td><td>SLCT 选择</td></tr>
	<tr><td>14</td><td>AUTO FEED 自动换行</td></tr>
	<tr><td>15</td><td>ERROR 错误</td></tr>
	<tr><td>16</td><td>INIT 初始化</td></tr>
	<tr><td>17</td><td>SLCT IN 选择输入</td></tr> 
   	<tr><td>18-25</td><td>GND 地线</td></tr>
</table> 
 
<h3><a name="topic45">发送暂停</a></h3>
 
<p>点击[Pause]按钮可以暂停发送发送队列中的内容。再按[Continue]继续发送。这里需要说明的是,在暂停时仍可使用直接CW键击发报。</p>
 
<hr>
<h2><a name="topic4a">网络通联</a></h2>
 
<p>Lakey现在可以支持网络通联,如果您希望与另一个HAM通过网络进行通联,那么需要进行以下两步操作:1、启用网络通联功能(参见:<a href="#topic55">网络</a>);2、了解对方的IP地址,并且在<a href="#topic55">网络</a>参数中,将对方IP地址添加到主机列表中。设置好以上两步,您所发送的摩尔斯电码将通过网络传送到对方主机,并通过扬声器和显示器传达给对方。</p>
 
<hr>
<h2><a name="topic5">参数调整</a></h2>
 
<h5>从菜单 - 工具->设置 可以进入配置界面:</h5>
<img src="images/img51.jpg" alt="Lakey配置界面 - CW规则参数">
<p><b>在这里可以对系统用到的大多数参数进行调整</b></p>
<h5>下面是这些对这些参数的详细说明:</h5>
 
<h3><a name="topic51">CW规则</a></h3>
 
<li><b>"滴"声长(ms):</b>摩尔斯电码中的短鸣声。</li>
<li><b>"哒"声长度(ms):</b>摩尔斯电码中的长鸣声。</li>
<li><b>键击间隔(ms):</b>在一个字符电码中按键的间隔。</li>
<li><b>字符间隔(ms):</b>字符与字符之间的延迟时间。</li>
<li><b>键速(wps):</b>按标准单词长度(1 word = “PARIS”),计算的发报速度。
 
<p>上面的规则即适用于发送,也适用于接收分析。应适当调整,以适应自身习惯和接收信号的特点。</p>
 
<h3><a name="topic52">发送</a></h3>
<br>
<img src="images/img52.jpg" alt="Lakey配置界面 - 发送参数">
<br>
</li>
<li><b>音调(Hz):</b>CW发送的嘀嗒声基准频率;缺省值,1KHz</li>
<li><b>音量(0~1):</b>CW发送的嘀嗒声音量。这里实际调整的是生成波形的振幅比例,1为最大,0为最小。具体输出音量也可以通过操作系统的“音量控制”来调节; 缺省值, 0.250000</li>
<li><b>采样间隔(ms): </b>对CW发送内容的采样间隔,适当提高采样间隔可以提高对发送内容分析精度。</li>
<li><b>空闲停止(ms):</b>当一定时间无输出时,停止记录,避免过多空白出现。</li>
<li><b>CW键:</b>这里是一个CW键的Win32键盘代码(Win32 Virtual key code),下面列出几个常用键代码:
<div class="comment">回车:13,空格:32,Shift:16,Tab:9,上:38,下:40,左:37,右:39</div>
</li>
<li><b>空格延迟(ms):</b>空格延迟时间长度。
 
<h3><a name="topic53">接收</a></h3>
<br>
<img src="images/img53.jpg" alt="Lakey配置界面 - 接收参数">
<br>
</li>
<li><b>采样数量:</b>每次分析接收音频的采样点数量,数值约大,精度约高;可以参考下面的规则:
<div class="comment">分析最小频率单位 = 44100 / 2 / 采样数量 = 22050 / 采样数量</div>
<p>但要注意的是,过多的采样数量会过多的消耗CPU资源,有可能造成对其他功能的影响!经测试,使用Intel(R) Core(TM)2 Duo T6670@2.2GHz,采样数量设定为256时,CPU占用率小于20%,平均为15%左右。</p>
</li>
<li><b>采样间隔(ms):</b>对CW接收内容的采样间隔;从b0017版开始,此数值已经不对接收内容分析精度有任何影响,而只影响分析的实时性。</li>
<li><b>空闲停止(ms):</b>当一定时间无接收内容时,停止记录,避免过多空白出现。</li>
<li><b>阀值电平(0~1):</b>只有大于这个输入电平的音频信号才被当作是摩尔斯电码信号进行分析。</li>
<li><b>起始频率(Hz) 和 截止频率(Hz):</b>只有大于起始频率和小于截止频率的信号分量才参与摩尔斯电码信号分析。这样可以起到过滤杂波的作用。接收的CW音频信号频率应该包含在起始频率至截止频率这个范围内,但要注意的是,这个范围不应过小,应该保持在200Hz以上。这个可以从介绍“采样数量”时提到的公式得到,如果过小的范围,将有可能不被包含在最小分析区间!
 
<h3><a name="topic54">练习</a></h3>
<br>
<img src="images/img54.jpg" alt="Lakey配置界面 - 练习参数">
<br>
</li>
<li><b>字符集:</b>指定在练习模式或生成的练习音频文件中使用的字符。字符可以重复,出现次数多的字符在练习时出现的概率也相应增加。</li>
 
<li><b>字长度:</b>指定在练习模式或生成的练习音频文件中多少字符为一组,组与组之间使用相当于空格延迟时间长度的空白分开。
 
<h3><a name="topic55">网络</a></h3>
<br>
<img src="images/img55.jpg" alt="Lakey配置界面 - 网络参数">
<br>
</li>
<li><b>本地端口:</b>用于网络通讯的SOCKET端口,UDP类型。</li>
 
<li><b>启用网络:</b>是否允许Lakey通过网络进行发送和接收操作。</li>
 
<li><b>主机 - IP/端口/列表:</b>录入对方主机IP地址和端口,点击右边的“添加”按钮,可以将录入的主机加入静态主机列表,在列表中的主机将能接收到您发送的摩尔斯信号。
 
<h3><a name="topic56">I/O</a></h3>
 
<br>
<img src="images/img56.jpg" alt="Lakey配置界面 - I/O参数">
<br>
</li>
<li><b>地址(HEX):</b>外部设备连接到计算机上端口的内部地址。如:打印端口通常为16进制的0378(默认)。为安全起见,此参数不能在此处修改。如有特别需要,可以调整Lakey.ini中的extportaddr属性值。</li>
 
<li><b>开启(HEX):</b>相当于电键按下时端口的输出状态。</li>
 
<li><b>关闭(HEX):</b>相当于电键抬起时端口的输出状态。
 
<p>上面的开启和关闭两个参数,对应端口的输出数据;如:当设置为01时,相应设置状态下的输出为16进制的01,对于0378并口来讲,就是2针(D0)为高电平,3-9针(D1-D7)为低电平。</p>
 
<h3><a name="topic58">参数调整失败怎么办?</a></h3>
 
<p>由于软件还处于测试期间,并未对参数进行合法性检查,如果不适当的调整参数,有可能造成软件不能启动。如果发生这种问题,可以把运行目录中的Lakey.ini文件删除,软件即可按照缺省参数启动。</p>
 
<hr>
<h2><a name="topic8">CW练习</a></h2>
 
<h5>Lakey可以在不使用外围电路的情况下,由键盘或鼠标键击发出di dah声,来练习发报,祥见:</h5>
</li>
<li><a href="#topic4">发报</a>
 
<h3><a name="topic81">开始进行Koch模式练习</h3>
 
<h5>从菜单 - 工具->Koch训练法或者使用快捷键[Ctrl+K]都可以启动Koch模式练习功能。</h5>
<p>启动时系统会提示如下图所示的对话框:</p>
<img src="images/img81.jpg" alt="Lakey Koch训练开始提示">
<p>点击[确定]按钮或按[回车]键,系统弹出抄录栏,同时开始自动发报,正式开始Koch模式练习。抄录栏如下图所示:</p>
<img src="images/img82.jpg" alt="Lakey Koch训练听抄录入界面">
<p>训练过程中,错码会用红色标出,并在窗口下部的统计栏内显示统计实时信息,供练习者参考。如下图所示。</p>
<img src="images/img83.jpg" alt="Lakey Koch训练成绩统计界面">
<p>抄录中途可以通过点击[完成]按钮来结束训练模式。再点击[关闭]按钮退出Koch训练模式。也可以点击[ESC]键直接退出训练模式。</p>
 
<h3><a name="topic83">生成抄报练习音频文件</a></h3>
 
<h5>从菜单 - 工具->生成CW音频文件。</h5>
<p>从这里可以生成任意字符的音频文件。</p>
 
<h5>从菜单 - 工具->生成Koch音频文件。</h5>
<p>从这里可以使用配置在<a href="#topic54">参数调整</a>中练习里的字符集,生成随机序列的音频文件。</p>
 
 
<h3><a name="topic85">发报练习</a></h3>

<h5>从菜单 - 工具->发报练习。<h5>
<p>Lakey会提示你选择一个文本文件,这个文件应含有报底文本。选择好文件后,您就可以开始发报了。
发报时Lakey会实时解析你所发送的Morse码,但并不会提示是否与报底相同。因此,你在练习时应确保发送的内容与报底同步,否则事后Lakey的正确率统计将会不正确。
当然,如果不同步也没有关系,如果对Lakey统计的正确率有疑问,可以到报底文件所在文件夹下寻找一个以报底文件名为前缀,后缀为“.jrn”的记录文件。
该文件会完整记录Lakey的解析结果,对于错误或者不认识的字符会以“#”替代。
</p>

<h2><a name="topic8a">CW练习技巧</h2>
 
<p>时下对CW感兴趣的HAM越来越多,这里搜集了几篇关于学习CW方法/技巧的文章,供朋友们参考。</p>
 
</li>
 
<li><a href="#topic8a1">古典练习法</a></li>
<li><a href="#topic8a2">Koch练习法</a></li>
<li><a href="#topic8a3">Farnsworth练习法</a>
 
<p>个人认为上面这几种方法在练习时选择其中一种即可,多种方法混用时可能会产生混乱。</p>
 
<p>文章全部从Internet上收集,其版权属于原作者所有,如被收集文章的作者认为文章出现在此处并不妥当,请联系我(联系方法在首页),我会立即从这里删除。</p>
 
<h3><a name="topic8a1">古典练习法</a></h3>
<i>(摘自BG1TGP在ham.it168.com论坛上发表的<a href="http://bbs.it168.com/viewthread.php?tid=362582&pid=1954353&page=1&extra=page%3D1#pid1954353">《致HAM初学CW的建议》一文 </a>)</i>
 
<h5>致HAM初学CW的建议</h5>
<p>给大家一点学习CW的建议,如果原先无基础还是先从记忆英文字母、数字、常用标点符号的电码符号开始,这是第一步也是基础,就象小学生学习一篇满是生字的课文一样,要想让别人听写你首先得能读下来,要想读下来首先得把生字认识了,那么所有字符对应的电码符号一共也就几十个这个应该不是什么问题吧.</p>
<p>另外还可以利用CW练习软件进行辅助练习,敲击键盘电脑就会发出字符对应的电码符号读音,电脑发完了你就跟它学着读速度不易过快,当你已经不能满足按照A----Z/0----9的有规律的报底的时候可以将顺序打乱编辑一段报底,还是由电脑领读你来学着读,将间隔时间设定的大一点留出你跟读的时间,这期间还可以穿插完全读报底的练习,对卡壳的字母重点练习,其实记忆的过程就是在不断的重复中实现的。</p>
<p>下一步我们就要跟电脑学习读报底的节奏了,将一些单词组成短句并用空格来隔出单词之间的间隙存在电脑里并抄写下来一份报底,还是由电脑来领读你来跟读,达到一定的熟练程度后可以试着和电脑同期读,重点是掌握正确的读音和节奏,期间可以随便找些英文的书或报纸等作为报底来读,你读的有多熟练就证明你记忆的有多熟练,和电脑同期练习时你读的和电脑发的有多同步就证明你将来发报时的节奏有多标准。这只是刚刚开始还没到练习收报的时候,这个阶段就是记忆---电脑领读你跟读---自己按报底读---和电脑同步读,总之就是一个字----读。</p>
<p>如果报文不长速度也不快不压码也可以,但是最好是养成压码收报的习惯,压码的好处是可以让你收报更轻松,比如当报文中出现E--I等电码符号特别短的字母连在一块的时候如果你不会压码收报就会觉得手忙脚乱,因为当你听到E的电码符号后需要大脑来辨别这个“嘀”是什么字母,然后手要把这个字母写下来或在键盘上撬出来,可是还没等你写完的时候第二I又来了,等你写第二个的时候第三个又来了,假如下一个是9你又会觉得时间太长还得等他一会,由于电码符号的长度不均匀就会出现上面的现象,这样的化你的书写势必会影响到你的听辨。收报的过程是耳朵听---大脑辨---手来写,节奏由各电码符号的时间长度决定,遇到符号少的时间就短要是几个连在一块就手忙脚乱,那么压码收报就可以把由于各字符电码符号时间长度不同带给你的处理时间不同的矛盾在一定程度上给化解了,当听辨出第一个电码后不下笔写先记在脑子里,集中精力听第二个,当听辨出来第二个电码后下笔写第一个,把第二个在记在脑子里集中精力听第三个依次类推,就是耳朵不停的听,脑袋不停的辨,手不停的写,压码的本领是通过训练获得的,刚开始可能不太习惯时间长了就好了,你会发现你的收报节奏不在受电码时间长度的影响完全在你的掌握之中,压一到两个码基本就够了就会轻松不少,试一试等你的好消息。</p>
 
<h4><a name="topic8a2">Koch练习法</a></h4>
<i>(摘自BG1WZ在www.hellocq.net论坛上名为<a href="http://www.hellocq.net/forum/showthread.php?t=29205&page=1&pp=30">《学习CW的捷径》的帖子及其回帖</a>)</i>
 
<p>Koch Method被证明是一种很少失败的训练方法。简单说来一开始只用标准速度(至少15 wpm)听2个字符,达到90%抄收的水平之后增加第三个字符,3个字符一起练习,再达到90%抄收的水平之后增加第四个字符,如此与时俱进,基本上使用高速度养成条件反射。训练选择的字符不从最简单的E或T开始,推荐的学习顺序是:</p>
<p><b>K M R S U A P T L O W I . N J E F 0 Y , V G 5 / Q 9 Z H 3 8 B ? 4 2 7 C 1 D 6 X &lt;BT&gt; &lt;SK&gt; &lt;AR&gt;</b></p>
 
<h5>译一篇文章——如果你希望学习莫尔斯码</h5>
<p><br><i>如果你希望学习莫尔斯码<br>
忘记挫折:获得有价值的莫尔斯技巧并增加你的业余无线电乐趣<br><br>
 
作者:Dave Finley, N1IRZ 译:BG1WZ(译者注:译文有删节)<br><br>
关于莫尔斯码训练的完整信息、CW操作、历史和更多,请参见作者的书:《莫尔斯码:突破障碍》(原名:《Morse Code: Breaking the Barrier》),由MFJ Enterprises, Inc.出版。<br></i>
</p>
<p>业余执照做了一些调整,你不再需要通过13或20wpm的考试才能获得完全的操作许可,只要通过5-wpm的考试就得到一切。但是为什么你不做得更多些?具有熟练的莫尔斯码水平,也就是可以抄收12-13 wpm或更多,能够从业余无线电的空中得到无限的乐趣。许多有兴趣的短波活动如远程接收,比赛和QRP操作是依靠CW完成的。数千ham把CW当做他们自己有别于其他通讯手段的休闲方式,甚至在VHF和更高的频率你可以发现激动人心的月面反射和弱信号通联仍然有赖于熟练的莫尔斯技巧。
一般认为达到13或20wpm速度几乎是不可逾越的障碍,这种理解是不对的。只要花费比通过5-wpm考试不多的时间投入,你就能得到真正高速的抄收能力,增强你对这一业余爱好的兴趣。你听到的许多有关学习莫尔斯码的说法是错误的——绝对错误。业余无线电界传统使用极慢的、最使人灰心丧气的、最痛苦和最无效的方法学习莫尔斯码。你能够获得真正的熟练技巧,你能够在相当短的时间内以最少的挫折和痛苦得到这些。它要求实地操作,你需要每天拿出15-30分钟进行训练直到达到目标。你可能在一个月或七个月内成功,个人的差异是巨大的。</p>
<p>这里有什么新方法?训练方法是德国心理学家Ludwig Koch在大约60年前发明的,最少的挫折和充分的加强使你可以尽快的进步。</p>
<p>让我们丢弃一些ham-radio传统上出现过的废物,开始走上成功之路。它们是:</p>
<p>●慢速(5
wpm)电码——用这个速度教任何人都应该看为非法的,绝对是一种浪费。而且保证会在将来出现困难以至学不下去。5 wpm和15或20wpm的电码完全是两回事,你当然不希望在错误上浪费时间。</p>
<p>●对照表,记忆术,音乐的暗示和其他记忆帮助——这些事情让你在试图抄收电码的时候还要想别的,对于精确抄收是致命的。</p>
<p>●训练磁带——很短时间内,你不知不觉的记忆了磁带的内容,并对自己的能力建立起虚假的信心。这种虚假的信心在你听到未曾记忆的电码时很快就会被粉碎。</p>
<p>●抄收空中的QSOs——你不知道频率上发码的速度,而且许多电码发得很差,无助于训练的目的。正规的练习课程例如W1AW所发的当然不在此例。</p>
<p>技巧:训练什么,怎样练?</p>
<p>去电报操作员的工作房间或参观俱乐部野外电台的CW操作,看一看他们在30到35
wpm速度的收和发。你将注意到他们做这些很轻松,并不费脑子,电码已经成为他们的第二语言。关键是熟练程度。抄收必须是无需思考的处理,听到就知道了,不用想它是什么。这是一种条件反射,实际上抄收速度超过10 wpm就只能靠反射,靠脑子想就太慢了。这就是为什么说过慢的速度是致命的陷阱,为什么传统的业余莫尔斯码训练痛苦又困难。许多ham先记忆了全部字符,然后开始提高速度。他们不断在脑子里查表,把听到的码与头脑里的表相比较,找出相符的。这样的处理到10 wpm左右就行不通了,所以经常有人停留在10 wpm的水平,数周或数月没有任何进步。
他们最终越过“驼峰”,超过10 wpm是因为持续的练习使他们用反射代替了思考,他们是幸运的。10 wpm的障碍使许多人在挫折面前选择了放弃。于是莫尔斯码训练完全避免“查表”阶段而用建立条件反射实现熟练的抄收。最初是1930年代德国心理学家Ludwig Koch认识到这一点,设计出非常有效的莫尔斯码训练方法。</p>
<p>用Koch方法练习莫尔斯码</p>
<p>Koch方法简单、直接地建立起条件反射。然而它要求一台电脑加软件或一个教师的协助,这也是它在过去许多年受到冷落的原因。现在电脑很普及,也有望成为标准的莫尔斯码训练方法。它的工作过程是:</p>
<p>准备好纸和铅笔,设置你的电脑(或微处理器构成的电码练习器)以20 wpm的速度发送莫尔斯字符(最少也要15 wpm)——但是仅仅2个字符。是的,这是第一课,你只有两种选择。在纸上抄收5分钟,停下机器,把你抄收的结果与机器发送的字符做比较,计算字符数目和抄收正确的百分比。</p>
<p>如果你的正确率是90%或更高——恭喜你!你已经学完了最初的2个字符。并且非常重要的,你是用全速学会的,再也不需要重新学习它们。如果你的正确率不足90%,需要继续练习。</p>
<p>一旦你抄收前2个字符达到90%的正确率,就在练习中增加第三个字符。增加新字符后你的正确率会下降,但是很快会上升到超过90%,这时再加上第四个字符,如此类推。</p>
<p>这个方法不允许你在脑子里建立一个对照表,为了90%正确率的全速抄收,你必须建立起条件反射,我们花费时间练习就是这个目的,就像练习打网球或体操一样,练习到你掌握了它。逐字学习的Koch方法有点和训练打字的盲打相像,那是另一个必须建立条件反射的技巧。</p>
<p>这是一个非常独特的训练方法——以你自己最好的速度前进,只为增加每个新字符花费时间,在达到目标的途中不浪费时间。</p>
<p>多少时间是必须的?这取决于个人。以Koch来说,他挑选的一组学生掌握12
wpm的电码平均仅用13.5小时。你也许不完全是这样,但它确实比心理学文献记录的任何方法更快。在熟练掌握一些字符之后你就能估算出总的学习时间。跟踪你的训练课程(一些软件可以为你做)并计花费在每个字符上的时间,乘上43(业余莫尔斯码考试所用)就是总的时间。</p>
<p>虽然Koch方法是练习莫尔斯码最快的方法,速度并不是它最基本的好处,基本的好处和它有别于其他训练方法的是让你不断的得到肯定和加强。随着你的实践,刚掌握2个字符时已经达到15或20 wpm,随后每一个新字符的加入都更多的验证了你的进步。与慢慢的建立4或5 wpm速度,碰到10 wpm的平台长时间不能进步相比,Koch方法可能遇到的挫折是最小的。</p>
<p>不断的测试是保证你使用Koch方法得到最大效益所必需的。必须抄收在纸上,这样才能给自己定级。一定要记住,如果准确率达到或超过90%就加一个字符。如果少于90%,要继续练习。最少每5分钟测试一次,决定什么时候增加字符,可以使进度最快。</p>
<p>使用Koch方法学习,直到你掌握完整的字符集之前,自然抄收的是随机的字符组而不是单词。如果你的软件允许,让这些字符具有随机的长度,而不是固定的5个字符一组,这样更接近实际的单词。单词和随机的字符组之间在节奏和“感觉”上确实存在差异。当你能够熟练抄收单词,就可以抄收简单的QSO,这是业余无线电考试的格式。特别留意呼号、位置和数字的抄收,这些内容往往成为考试重点。
</p>
 
<h4><a name="topic8a3">Farnsworth练习法</a></h4>
<i>(摘自BG1WZ在www.hellocq.net论坛上名为<a href="http://www.hellocq.net/forum/showthread.php?t=29205&page=1&pp=30">《学习CW的捷径》的帖子及其回帖</a>)</i>
 
<h5>学习CW的捷径</h5>
<p>近日浏览了几个莫尔斯码学习软件,几乎都提到了Farnsworth
Method,于是又去搜索法恩斯沃斯方法的含义,中文内容竟然搜索不到(繁体的有一条)。只好费劲读英文,读过几段总算基本弄清了,现在把有关情况作一介绍,也许对新手学习CW有所帮助。</p>
<p>'Farnsworth'(法恩斯沃斯)方法的中心就是对于初学者不过分降低每个字符的发送速度(一般为每分钟15-18词wpm),只是加大字符之间的空隙(例如使用5wpm的空间)。一旦你确认能够分辩出每个字母、数字、符号,就开始减少字符间的空隙。</p>
<p>这时每个字符的声音没有改变——你已经熟悉了,不用再次学习,因此很快可以把速度提上去。更慢的字符速度会诱使你去数点和划,造成更难于按它有特性的节奏声音去识别的困难。</p>
<p>许多CW软件的作者(基本上都是ham)反对背记字符/莫尔斯码对照表。因为那样学习的结果会导致听到电码之后再到脑子里去“查表”,速度很难提高。他们也反对背记分离的di dah,提倡把一个字符的CW码作为一个声音来记忆。我理解这样记忆的结果不但反应速度快,点/划/空间的比率也不用考虑,一起记忆了。</p>
 
<hr>
<h2><a name="topic6">系统需求</a></h2>
<br>
</li>
<li>支持DirectSound的全双工声卡</li>
<li>P3或同级别CPU</li>
<li>IP网络适配器(可选)</li>
<li>并行/串行接口(可选)

<hr>
<h2><a name="topic7">版本更新历史</a></h2>
<br>
 
</li>
 
<li style="color: red;">
  Version 2.1.0019 Pencil(铅笔) (2012-6-30)

  <p>实现了由BA3CE建议的发送练习功能,并能够将练习时发送的文本记录下来;</p>
  <p>新增加的频谱显示将频率坐标轴方向反向,即频率较低的数据显示在靠下的位置;</p>

</li>

<li>
  Version 2.0.0018 Zongzi(粽子) (2012-6-22)

  <p>正式引入FFT算法,大幅降低精确音频分析的CPU占用率;</p>
  <p>基于CPU占用率的降低,默认的FFT(原DFT)采样数量增加为512(实际使用可以更高);</p>
  <p>增加了结合频率、时间、能量的频谱图;</p>
  <p>修正了自动键的问题(感谢BG8ST及其他提出了此问题但没有留下呼号的朋友)</p>
  <p>修正了“/”符号的Morse编码错误(感谢BD1GXH);</p>
  <p>修正了底层图形API(复制图层)的一个缺陷(过去有些控件显示可能会有拖尾无法擦净);</p>
  <p>从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号;</p>

</li>

<li>Version 1.1.0017 BETA (2010-8-15) 
 
<p>采样数默认值减至256每秒,以降低CPU使用率;</p>
<p>接收音频完整数据分析(过去为抽样分析);</p>
<p>改进摩尔斯解析算法,增加对抖动的过滤,提高准确性(包括接收和发送);</p>

</li>

<li>Version 1.1.0016 BETA (2010-8-14) 
 
<p>FFT计算精度由64位降低为32位,减少内存占用;</p>
<p>优化了代码, 修正一些变量的类型, 避免过多类型转换;</p>
<p>解决了按住空格画面显示错乱的问题;</p>
<p>手册错字修正;</p>

</li>

<li>Version 1.1.0015 BETA (2010-8-12) 
 
<p>增加音量\键速等控制旋钮及基础控件;</p>
<p>网络通联自动识别记录对方IP地址, 这样只要发送放设置对方IP即可;</p>
<p>取消精简模式(从初始版本一直以来的界面);</p>
<p>完善配置缺省值, 只要删除lakey.ini, 界面自动恢复为英文缺省界面;</p>

</li>

<li>Version 1.1.0014 BETA (2010-8-2) 
 
<p>增加模拟干扰信号;</p>
<p>界面文字完全可配置,并增加纯中文界面版本;</p>
<p>更正版本序列;</p>

</li>

<li>Version 1.1.0013 BETA (2010-5-2) 
 
<p>频谱分析增加对数和线性标尺;</p>
<p>频谱分析窗口样式改进;</p>
<p>改进了频谱分析状态提示;</p>

</li>

<li>Version 1.1.0012 BETA (2010-4-17) 
 
<p>修正了没有处理Win32消息返回值的错误,解决屏幕闪动的问题;</p>
<p>修正了当发送队列不为空时退出有时报错的问题;</p>
<p>增加了黑色;</p>

</li>

<li>Version 1.1.0011 BETA (2010-4-14) 
 
<p>增加了自动键模拟功能;</p>
<p>波形和频谱分析按比例完全显示(过去显示不全);</p>
<p>波形显示可放大幅度(鼠标左键切换);</p>
<p>频谱分析可按线性和对数两种方式显示(鼠标右键切换);</p>
<p>修正了DCT采样数量小于频谱分析控件宽度时报错的问题。</p>

</li>

<li>Version 1.1.0010 BETA (2010-4-5) 
 
<p>增加了对网络通联的支持;</p>
<p>标准控件改用系统主题风格(Windows XP版本以上);</p>
<p>加粗摩尔斯码记录条。</p>
 
</li>
 
<li>Version 1.0.0009 BETA (2009-11-22) 
 
<p>增加了设置wpm值的功能, 同时提供从复杂参数到wpm的反算功能;</p>
<p>增加了对硬件端口输出额外的控制,可使硬件端口只在需要的时候输出;</p>
<p>使用手册改为HTML格式。</p>
 
</li>
 
<li>Version 1.0.0008 BETA (2007-11-6) 
 
<p>增加了通过并行端口对外部设备进行控制的功能;</p>
<p>更新了用户手册。</p>
 
</li>
 
<li>Version 1.0.0007 RELEASE (2007-10-30) 
 
<p>修正了KOCH训练模式下,正常结束后不能再次启动训练模式的问题;</p>
<p>第一个稳定版本。</p>
 
</li>
 
<li>Version 1.0.0006 BETA (2007-7-10) 
 
<p>增加生成KOCH训练CW音频文件功能;</p>
<p>增加生成任意字符串CW音频文件功能;</p>
<p>改进分段、空格策略。</p>
 
</li>
 
<li>Version 1.0.0005 BETA (2007-3-29)
<p>使用红色实时标记Koch模式训练时输入的错码;</p>
<p>增加Koch模式训练统计功能。</p>
 
</li>
 
<li>Version 1.0.0004 BETA (2007-3-28)
<p>取得《中华人民共和国业余无线电台执照》及呼号特别纪念^_^;</p>
<p>增加Koch CW训练功能;</p>
<p>帮助文档中增加3篇有关CW学习方法的文章;</p>
<p>调整菜单布局。</p>
 
</li>
 
<li>Version 1.0.0003 BETA (2006-9-1)
<p>增加了参数配置界面;</p>
<p>增加了可以调整的音频分析精度;</p>
<p>增加了CHM版本的用户手册。</p>
 
</li>
 
<li>Version 1.0.0002 BETA (2006-8-28)
<p>增加了发送暂停功能;</p>
<p>增加了发送文本文件(只包含Morse code中的英文/数字/标点);</p>
<p>增加了发送队列的长度到8192;</p>
<p>修正了发送队列与显示不同步的问题。</p>
 
</li>
 
<li>Version 1.0.0001 BETA (2006-8-27)
<p>初始版本。</p>
 
</li>
 
</body>
</html>



================================================
FILE: src/CommFunc.cpp
================================================
#include "stdafx.h"
#include "Lakey.h"
#include "windows.h"
#include "Richedit.h"
#include "commctrl.h"
#include <time.h>
#include <ctype.h>

#include "LakeyMainWindow.h"
#include "CommFunc.h"

BOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		GetDlgItemText(hDlg, nItemId, lpTxtBuf, nMaxLen);
		return TRUE;
	}

	return FALSE;
}

BOOL SetDlgItemDec(HWND hDlg, UINT nItemId, double val)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		sprintf(vBuff, "%.4lf", val);
		SetDlgItemText(hDlg, nItemId, vBuff);
		return TRUE;
	}

	return FALSE;
}

BOOL GetDlgItemDec(HWND hDlg, UINT nItemId, double* pVal)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
		sscanf(vBuff, "%lf", pVal);
		return TRUE;
	}

	return FALSE;
}

BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, BYTE val)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		sprintf(vBuff, "%2.2hX", val);
		SetDlgItemText(hDlg, nItemId, vBuff);
		return TRUE;
	}

	return FALSE;
}

BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, BYTE* pVal)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
		WORD w = 0;
		sscanf(vBuff, "%hX", &w);
		*pVal = (BYTE)w;
		return TRUE;
	}

	return FALSE;
}

BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, WORD val)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		sprintf(vBuff, "%4.4hX", val);
		SetDlgItemText(hDlg, nItemId, vBuff);
		return TRUE;
	}

	return FALSE;
}

BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, WORD* pVal)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
		sscanf(vBuff, "%hX", pVal);
		return TRUE;
	}

	return FALSE;
}

BOOL GetDlgItemInt(HWND hDlg, UINT nItemId, int* pVal)
{
	if (GetDlgItem(hDlg, nItemId))
	{
		char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
		GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
		sscanf(vBuff, "%d", pVal);
		return TRUE;
	}

	return FALSE;
}



================================================
FILE: src/CommFunc.h
================================================
#pragma once

#include "stdlib.h"

BOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen);
BOOL SetDlgItemDec(HWND hDlg, UINT nItemId, double val);
BOOL GetDlgItemDec(HWND hDlg, UINT nItemId, double* pVal);
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, BYTE val);
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, BYTE* pVal);
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, WORD val);
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, WORD* pVal);
BOOL GetDlgItemInt(HWND hDlg, UINT nItemId, int* pVal);



================================================
FILE: src/EventListener.cpp
================================================
#include "StdAfx.h"
#include "EventListener.h"


================================================
FILE: src/EventListener.h
================================================
#pragma once

#include "Graphics.h"

class IEventListener
{
};

class IClickEventListener
{
public:
	virtual BOOL OnClick(void* owner) = 0;
};

class IPaintEventListener
{
public:
//	virtual BOOL OnErase(void* owner, CGraphics* g, const RECT* pRect) = 0;
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect) = 0;
};

class IMouseMoveEventListener
{
public:
	virtual BOOL OnMouseMove(void* owner, int x, int y) = 0;
};

class IKeyboardEventListener : public IClickEventListener
{
public:
	virtual BOOL OnKeyDown(void* owner, int nKeyCode) = 0;
	virtual BOOL OnKeyUp(void* owner, int nKeyCode) = 0;
};

class IMouseKeyEventListener : public IClickEventListener
{
public:
	typedef enum { LBUTTON = 1, CBUTTON, RBUTTON } MouseKeyType;

public:
	virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y) = 0;
	virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y) = 0;
};

class ITimerEventListener
{
public:
	virtual BOOL OnTimer(void* owner, int nTimerId) = 0;
};

class ICommandEventListener
{
public:
	virtual BOOL OnCommand(void* owner, int nCommId) = 0;
};



================================================
FILE: src/EventManagerWin32.cpp
================================================
#include "StdAfx.h"
#include "eventmanagerwin32.h"

CEventDispatcherWin32::CEventDispatcherWin32(HWND hWnd)
{
	m_hWnd = hWnd;
	m_pGraphics = new CGraphics(hWnd);
}

CEventDispatcherWin32::~CEventDispatcherWin32(void)
{
	delete m_pGraphics;
}

BOOL CEventDispatcherWin32::OnMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	BOOL r = FALSE;

	switch (message) 
	{
		case WM_ERASEBKGND:
			r = EraseProc(); break;
		case WM_PAINT:
			r = PaintProc(); break;
		case WM_MOUSEMOVE:
			r = MouseMoveProc(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
		case WM_KEYDOWN:
			r = KeyDownProc((int)wParam); break;
		case WM_KEYUP:
			r = KeyUpProc((int)wParam); break;
		case WM_LBUTTONDOWN:
			r = MouseKeyDownProc(IMouseKeyEventListener::LBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
		case WM_LBUTTONUP:
			r = MouseKeyUpProc(IMouseKeyEventListener::LBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
		case WM_RBUTTONDOWN:
			r = MouseKeyDownProc(IMouseKeyEventListener::RBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
		case WM_RBUTTONUP:
			r = MouseKeyUpProc(IMouseKeyEventListener::RBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
		case WM_TIMER:
			r = TimerProc((int)wParam); break;
		case WM_COMMAND:
		{
			int nCtrlId = LOWORD(wParam);
			if (nCtrlId)
				r = CommandProc(nCtrlId);
			break;
		}
	}

	return r;
}

void CEventDispatcherWin32::AddPaintEventControl(IPaintEventControl* pCtrl)
{
	m_oPaintEventControls.push_back(pCtrl);
}

void CEventDispatcherWin32::AddMouseMoveEventControl(IMouseMoveEventControl* pCtrl)
{
	m_oMouseMoveEventControls.push_back(pCtrl);
}

void CEventDispatcherWin32::AddKeyboardEventControl(IKeyboardEventControl* pCtrl)
{
	m_oKeyboardEventControls.push_back(pCtrl);
}

void CEventDispatcherWin32::AddMouseKeyEventControl(IMouseKeyEventControl* pCtrl)
{
	m_oMouseKeyEventControls.push_back(pCtrl);
}

void CEventDispatcherWin32::AddTimerEventControl(ITimerEventControl* pCtrl, int nTimerId, int nInterval)
{
	m_oTimerEventControls.push_back(pCtrl);
	SetTimer(m_hWnd, nTimerId, nInterval, NULL);
}

void CEventDispatcherWin32::AddCommandEventControl(ICommandEventControl* pCtrl)
{
	m_oCommandEventControls.push_back(pCtrl);
}

void CEventDispatcherWin32::RemovePaintEventControl(IPaintEventControl* pCtrl)
{
	for (vector<IPaintEventControl *>::iterator it = m_oPaintEventControls.begin();
		it != m_oPaintEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oPaintEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::RemoveMouseMoveEventControl(IMouseMoveEventControl* pCtrl)
{
	for (vector<IMouseMoveEventControl *>::iterator it = m_oMouseMoveEventControls.begin();
		it != m_oMouseMoveEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oMouseMoveEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::RemoveKeyboardEventControl(IKeyboardEventControl* pCtrl)
{
	for (vector<IKeyboardEventControl *>::iterator it = m_oKeyboardEventControls.begin();
		it != m_oKeyboardEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oKeyboardEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::RemoveMouseKeyEventControl(IMouseKeyEventControl* pCtrl)
{
	for (vector<IMouseKeyEventControl *>::iterator it = m_oMouseKeyEventControls.begin();
		it != m_oMouseKeyEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oMouseKeyEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::RemoveTimerEventControl(ITimerEventControl* pCtrl)
{
	for (vector<ITimerEventControl *>::iterator it = m_oTimerEventControls.begin();
		it != m_oTimerEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oTimerEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::RemoveCommandEventControl(ICommandEventControl* pCtrl)
{
	for (vector<ICommandEventControl *>::iterator it = m_oCommandEventControls.begin();
		it != m_oCommandEventControls.end();
		++it)
	{
		if (pCtrl == (*it))
		{
			m_oCommandEventControls.erase(it);
			break;
		}
	}
}

void CEventDispatcherWin32::Invalidate(const RECT* pRect)
{
	::InvalidateRect(m_hWnd, pRect, TRUE);
}

CGraphics* CEventDispatcherWin32::NewGraphics(int w, int h)
{
	HDC hDc = GetDC(m_hWnd);
	CGraphics* g = new CGraphics(hDc, w, h);
	ReleaseDC(m_hWnd, hDc);
	return g;
}

BOOL CEventDispatcherWin32::EraseProc()
{
//	m_pGraphics->SetErase();
	return TRUE;
}

BOOL CEventDispatcherWin32::PaintProc()
{
	BOOL r = FALSE;
	m_pGraphics->BeginPaint();
	for (vector<IPaintEventControl *>::iterator it = m_oPaintEventControls.begin();
		it != m_oPaintEventControls.end();
		++it)
	{
		RECT cr, dr;
		(*it)->GetRect(&cr);
		const RECT* pRect = m_pGraphics->GetPaintRect();
		if (NULL == pRect || IntersectRect(&dr, pRect, &cr))
		{
			OffsetRect(&dr, -cr.left, -cr.top);
			m_pGraphics->SetOrigin(cr.left, cr.top);
			r |= (*it)->OnPaint((*it), m_pGraphics, &dr);
		}
	}
	m_pGraphics->EndPaint();

	return r;
}

BOOL CEventDispatcherWin32::MouseMoveProc(int x, int y)
{
	BOOL r = FALSE;
	for (vector<IMouseMoveEventControl *>::iterator it = m_oMouseMoveEventControls.begin();
		it != m_oMouseMoveEventControls.end();
		++it)
	{
		if ((*it)->IsRelated(x, y))
		{
			RECT cr;
			(*it)->GetRect(&cr);
			r |= (*it)->OnMouseMove((*it), x - cr.left, y - cr.top);
		}
	}

	return r;
}

BOOL CEventDispatcherWin32::KeyDownProc(int nKeyCode)
{
	BOOL r = FALSE;
	for (vector<IKeyboardEventControl *>::iterator it = m_oKeyboardEventControls.begin();
		it != m_oKeyboardEventControls.end();
		++it)
	{
		r |= (*it)->OnKeyDown((*it), nKeyCode);
	}

	return r;
}

BOOL CEventDispatcherWin32::KeyUpProc(int nKeyCode)
{
	BOOL r = FALSE;
	for (vector<IKeyboardEventControl *>::iterator it = m_oKeyboardEventControls.begin();
		it != m_oKeyboardEventControls.end();
		++it)
	{
		r |= (*it)->OnKeyUp((*it), nKeyCode);
	}

	return r;
}

BOOL CEventDispatcherWin32::MouseKeyDownProc(IMouseKeyEventControl::MouseKeyType nMkt, int x, int y)
{
	BOOL r = FALSE;
	for (vector<IMouseKeyEventControl *>::iterator it = m_oMouseKeyEventControls.begin();
		it != m_oMouseKeyEventControls.end();
		++it)
	{
		if ((*it)->IsRelated(x, y))
		{
			RECT cr;
			(*it)->GetRect(&cr);
			r |= (*it)->OnMouseKeyDown((*it), nMkt, x - cr.left, y - cr.top);
		}
	}

	return r;
}

BOOL CEventDispatcherWin32::MouseKeyUpProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y)
{
	BOOL r = FALSE;
	for (vector<IMouseKeyEventControl *>::iterator it = m_oMouseKeyEventControls.begin();
		it != m_oMouseKeyEventControls.end();
		++it)
	{
		if ((*it)->IsRelated(x, y))
		{
			RECT cr;
			(*it)->GetRect(&cr);
			r |= (*it)->OnMouseKeyUp((*it), nMkt, x - cr.left, y - cr.top);
		}
	}

	return r;
}

BOOL CEventDispatcherWin32::TimerProc(int nTimerId)
{
	BOOL r = FALSE;
	for (vector<ITimerEventControl *>::iterator it = m_oTimerEventControls.begin();
		it != m_oTimerEventControls.end();
		++it)
	{
		r |= (*it)->OnTimer((*it), nTimerId);
	}

	return r;
}

BOOL CEventDispatcherWin32::CommandProc(int nCommId)
{
	BOOL r = FALSE;
	for (vector<ICommandEventControl *>::iterator it = m_oCommandEventControls.begin();
	it != m_oCommandEventControls.end();
		++it)
	{
		r |= (*it)->OnCommand((*it), nCommId);
	}

	return r;
}

BOOL IControl::PointInRect(const RECT* pRect, int x, int y)
{
	POINT pt;
	pt.x = x;
	pt.y = y;

	return ::PtInRect(pRect, pt);
}

BOOL IControl::IntersectRect(RECT* pDest, const RECT* pSrc1, const RECT* pSrc2)
{
	return ::IntersectRect(pDest, pSrc1, pSrc2);
}




================================================
FILE: src/EventManagerWin32.h
================================================
#pragma once

#include <vector>

#include "Graphics.h"
#include "EventListener.h"

using namespace std;

class IControl
{
public:
	virtual BOOL IsRelated(int x, int y) = 0;
	virtual void GetRect(RECT* r) = 0;

	static BOOL PointInRect(const RECT* pRect, int x, int y);
	static BOOL IntersectRect(RECT* pDest, const RECT* pSrc1, const RECT* pSrc2);
};

class IPaintEventControl : public IControl, public IPaintEventListener
{
};

class IMouseMoveEventControl : public IControl, public IMouseMoveEventListener
{
};

class IKeyboardEventControl : public IKeyboardEventListener
{
};

class IMouseKeyEventControl : public IControl, public IMouseKeyEventListener
{
};

class ITimerEventControl : public ITimerEventListener
{
};

class ICommandEventControl : public ICommandEventListener
{
};

class IUserData
{
public:
	virtual void SetUserData(void* pUserData) = 0;
	virtual void* GetUserData() = 0;
};

class IPaintableParent
{
public:
	virtual void Invalidate(const RECT* pRect) = 0;
	virtual CGraphics* NewGraphics(int w, int h) = 0;
};

class CEventDispatcherWin32
	: public IPaintableParent
{
public:
	CEventDispatcherWin32(HWND hWnd);
	virtual ~CEventDispatcherWin32(void);

	virtual BOOL OnMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);

	virtual void AddPaintEventControl(IPaintEventControl* pCtrl);
	virtual void AddMouseMoveEventControl(IMouseMoveEventControl* pCtrl);
	virtual void AddKeyboardEventControl(IKeyboardEventControl* pCtrl);
	virtual void AddMouseKeyEventControl(IMouseKeyEventControl* pCtrl);
	virtual void AddTimerEventControl(ITimerEventControl* pCtrl, int nTimerId, int nInterval);
	virtual void AddCommandEventControl(ICommandEventControl* pCtrl);

	virtual void Invalidate(const RECT* pRect);
	virtual CGraphics* NewGraphics(int w, int h);

	virtual BOOL EraseProc();
	virtual BOOL PaintProc();
	virtual BOOL MouseMoveProc(int x, int y);
	virtual BOOL KeyDownProc(int nKeyCode);
	virtual BOOL KeyUpProc(int nKeyCode);
	virtual BOOL MouseKeyDownProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y);
	virtual BOOL MouseKeyUpProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y);
	virtual BOOL TimerProc(int nTimerId);
	virtual BOOL CommandProc(int nCommId);

	virtual void RemovePaintEventControl(IPaintEventControl* pCtrl);
	virtual void RemoveMouseMoveEventControl(IMouseMoveEventControl* pCtrl);
	virtual void RemoveKeyboardEventControl(IKeyboardEventControl* pCtrl);
	virtual void RemoveMouseKeyEventControl(IMouseKeyEventControl* pCtrl);
	virtual void RemoveTimerEventControl(ITimerEventControl* pCtrl);
	virtual void RemoveCommandEventControl(ICommandEventControl* pCtrl);

protected:
	HWND GetHWnd() { return m_hWnd; };
	CGraphics* GetGraphics() { return m_pGraphics; };

private:
	vector<IPaintEventControl *>		m_oPaintEventControls;
	vector<IMouseMoveEventControl *>	m_oMouseMoveEventControls;
	vector<IKeyboardEventControl *>		m_oKeyboardEventControls;
	vector<IMouseKeyEventControl *>		m_oMouseKeyEventControls;
	vector<ITimerEventControl *>		m_oTimerEventControls;
	vector<ICommandEventControl *>		m_oCommandEventControls;

	CGraphics*		m_pGraphics;
	HWND			m_hWnd;
};



================================================
FILE: src/FFT.cpp
================================================
#include "StdAfx.h"
#include "fft.h"
#include <complex>


================================================
FILE: src/FFT.h
================================================
#pragma once

#include <math.h>

#ifdef PI
#undef PI
#endif

#define PI		3.1415926f

/**
 * class T: unit of external stored
 * class V: unit of internal handled
 */

template <class T, class V> class IFilterDFT
{
public:
	virtual T OnEncodeFilter(V val, int i) = 0;
	virtual T OnDecodeFilter(V val, int i) = 0;
};

template <class T, class V> class TCosDFT
{
public:
	TCosDFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter = NULL);
	~TCosDFT(void);
	void Encode(T* pDest, const T* pSrc);
	void Decode(T* pDest, const T* pSrc);

private:
	int			m_nAnalyzeSamples;
	V**	m_ppCosTab;
	IFilterDFT<T, V>* m_pFilter;
};

template <class T, class V> class TSinDFT
{
public:
	TSinDFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter = NULL);
	~TSinDFT(void);
	void Encode(T* pDest, const T* pSrc);
	void Decode(T* pDest, const T* pSrc);

private:
	int			m_nAnalyzeSamples;
	V**	m_ppSinTab;
	IFilterDFT<T, V>* m_pFilter;
};

template <class T, class V> class TFastFT
{
public:
	TFastFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter = NULL);
	~TFastFT(void);
	void Encode(T* pDest, const T* pSrc);
	void Decode(T* pDest, const T* pSrc);

private:
	void		fftCore();
	int			m_nAnalyzeSamples;
	int			m_nLog2;
	V*			m_vBuf[2];

	IFilterDFT<T, V>* m_pFilter;
};

template <class T, class V> 
TFastFT<T, V>::TFastFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter/* = NULL*/)
{
	m_nAnalyzeSamples = nAnalyzeSamples;
	m_pFilter = pFilter;
	m_vBuf[0] = new V[m_nAnalyzeSamples];	// real
	m_vBuf[1] = new V[m_nAnalyzeSamples];	// imod

	for (m_nLog2 = 0; nAnalyzeSamples > 1; ++m_nLog2)
	{
		nAnalyzeSamples >>= 1;
	}
}

template <class T, class V> 
TFastFT<T, V>::~TFastFT(void)
{
	delete[] m_vBuf[0];
	delete[] m_vBuf[1];
}

template <class T, class V> 
TCosDFT<T, V>::TCosDFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter/* = NULL*/)
{
	m_nAnalyzeSamples = nAnalyzeSamples;
	m_ppCosTab = new V*[m_nAnalyzeSamples];
	m_pFilter = pFilter;

	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		m_ppCosTab[i] = new V[m_nAnalyzeSamples];

		for (int x = 0; x < m_nAnalyzeSamples; ++x)
			m_ppCosTab[i][x] = cos(((x * 2) + 1) * i * PI / (2 * m_nAnalyzeSamples));
	}
}

template <class T, class V> 
TCosDFT<T, V>::~TCosDFT(void)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
		delete[] m_ppCosTab[i];

	delete[] m_ppCosTab;
}

template <class T, class V> 
TSinDFT<T, V>::TSinDFT(int nAnalyzeSamples, IFilterDFT<T, V>* pFilter/* = NULL*/)
{
	m_nAnalyzeSamples = nAnalyzeSamples;
	m_ppSinTab = new V*[m_nAnalyzeSamples];
	m_pFilter = pFilter;

	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		m_ppSinTab[i] = new V[m_nAnalyzeSamples];

		for (int x = 0; x < m_nAnalyzeSamples; ++x)
			m_ppSinTab[i][x] = sin(((x * 2) + 1) * i * PI / (2 * m_nAnalyzeSamples));
	}
}

template <class T, class V> 
TSinDFT<T, V>::~TSinDFT(void)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
		delete[] m_ppSinTab[i];

	delete[] m_ppSinTab;
}

template <class T, class V> 
void TSinDFT<T, V>::Encode(T* pDest, const T* pSrc)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		V c = 0;
		for (int x = 0; x < m_nAnalyzeSamples; ++x)
		{
			c += pSrc[x] * m_ppSinTab[i][x];
		}
		pDest[i] = m_pFilter ? m_pFilter->OnEncodeFilter(2 * c / m_nAnalyzeSamples, i) 
			: (T)(2 * c / m_nAnalyzeSamples);
	}
}

template <class T, class V> 
void TCosDFT<T, V>::Encode(T* pDest, const T* pSrc)
{
	V s = 0;
	static int ddd = 100;
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		V c = 0;
		for (int x = 0; x < m_nAnalyzeSamples; ++x)
		{
			c += pSrc[x] * m_ppCosTab[i][x];
		}
		pDest[i] = m_pFilter ? m_pFilter->OnEncodeFilter(2 * c / m_nAnalyzeSamples, i) 
			: (T)(2 * c / m_nAnalyzeSamples);

		s += abs(pDest[i]);
	}

	if (!(0 != ddd || 1.0 < s))
	{
		ddd = 0;
	}

	if (0 < ddd)
		--ddd;

}

template <class T, class V> 
void TSinDFT<T, V>::Decode(T* pDest, const T* pSrc)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		V c = 0;
		for (int x = 0; x < m_nAnalyzeSamples; ++x)
		{
			c += pSrc[x] * m_ppSinTab[i][x];
		}
		pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter(c, i) 
			: (T)c;
	}
}

template <class T, class V> 
void TCosDFT<T, V>::Decode(T* pDest, const T* pSrc)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		V c = 0;
		for (int x = 0; x < m_nAnalyzeSamples; ++x)
		{
			c += pSrc[x] * m_ppCosTab[i][x];
		}
		pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter(c, i) 
			: (T)c;
	}
}

template <class T, class V> 
void TFastFT<T, V>::Encode(T* pDest, const T* pSrc)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		m_vBuf[0][i] = (V)pSrc[i];
		m_vBuf[1][i] = (V)0;
	}

	fftCore();

	int n = m_nAnalyzeSamples / 2;
	V x, y;

	// ֪ΪɶFFT任зֱʽһ룬ΪԳƣֲ
	// ԭƵ(LaWaveCapture)ʾֻҪȡһ뼴
	if (m_pFilter)
	{
		for (int i = 0; i < n; ++i)
		{
			x = m_vBuf[0][i];
			y = m_vBuf[1][i];
			//pDest[i] = (T)m_vBuf[0][i];
			pDest[i * 2] = m_pFilter->OnEncodeFilter(sqrt(x * x + y * y), i * 2);

			x = m_vBuf[0][m_nAnalyzeSamples - i - 1];
			y = m_vBuf[1][m_nAnalyzeSamples - i - 1];
			pDest[i * 2 + 1] = m_pFilter->OnEncodeFilter(sqrt(x * x + y * y), i * 2 + 1);
		}
	}
	else
	{
		for (int i = 0; i < m_nAnalyzeSamples; ++i)
		{
			x = m_vBuf[0][i];
			y = m_vBuf[1][i];
			//pDest[i] = (T)m_vBuf[0][i];
			pDest[i * 2] = sqrt(x * x + y * y);

			x = m_vBuf[0][m_nAnalyzeSamples - i - 1];
			y = m_vBuf[1][m_nAnalyzeSamples - i - 1];
			pDest[i * 2 + 1] = sqrt(x * x + y * y);
		}
	}
}

template <class T, class V> 
void TFastFT<T, V>::Decode(T* pDest, const T* pSrc)
{
	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		m_vBuf[0][i] = (V)pSrc[i];
		m_vBuf[1][i] = (V)0;
	}

	fftCore();

	for (int i = 0; i < m_nAnalyzeSamples; ++i)
	{
		//pDest[i] = (T)(m_vBuf[0][i] / m_nAnalyzeSamples);
		pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter((T)m_vBuf[0][i], i) 
			: (T)m_vBuf[0][i];
	}
}

template <class T, class V> 
void TFastFT<T, V>::fftCore()
{
	int np, lmx, lix, nv2, npm1, lo, lm, li, j1, j2, i, j, k, l;
	V scl, arg, s, c, t1, t2;

	np = m_nAnalyzeSamples;
	l = m_nLog2;
	
	lmx = np;
	scl = 2 * PI / np;
	for (lo = 0; lo < l; ++lo)
	{
		lix = lmx;
		lmx = lmx / 2;
		arg = 0;
		for (lm = 0; lm < lmx; ++lm)
		{
			c = cos(arg);
			s = sin(arg);
			arg = arg + scl;
			for (li = lix; li <= np; li += lix)
			{
				j1 = li - lix + lm;
				j2 = j1 + lmx;
				t1 = m_vBuf[0][j1] - m_vBuf[0][j2];
				t2 = m_vBuf[1][j1] - m_vBuf[1][j2];
				m_vBuf[0][j1] += m_vBuf[0][j2];
				m_vBuf[1][j1] += m_vBuf[1][j2];
				m_vBuf[0][j2] = c * t1 + s * t2;
				m_vBuf[1][j2] = c * t2 - s * t1;
			} // for li
		} // for lm

		scl *= 2;
	} // for lo

	j = 0;
	nv2 = np / 2;
	npm1 = np - 1;
	for (i = 0; i < npm1; ++i)
	{
		if (i < j)
		{
			t1 = m_vBuf[0][j];
			t2 = m_vBuf[1][j];
			m_vBuf[0][j] = m_vBuf[0][i];
			m_vBuf[1][j] = m_vBuf[1][i];
			m_vBuf[0][i] = t1;
			m_vBuf[1][i] = t2;
		}

		k = nv2;
		while(k - 1 < j)
		{
			j -= k;
			k /= 2;
		}
		j += k;
	}
}

================================================
FILE: src/Graphics.cpp
================================================
#include "StdAfx.h"
#include "graphics.h"
#include "stdio.h"

CGraphics::CGraphics(HWND hWnd)
{
	m_hWnd = hWnd;
	GetClientRect(m_hWnd, &m_oSize);
	HDC hDc = GetDC(m_hWnd);
	m_hDc = ::CreateCompatibleDC(hDc);
	m_hBgBm = ::CreateCompatibleBitmap(hDc, m_oSize.right, m_oSize.bottom);
	SelectObject(m_hDc, m_hBgBm);
	ReleaseDC(m_hWnd, hDc);

	SetOrigin(0, 0);

	m_nColor = RGB(0, 0, 0);
	//m_nBgColor = RGB(224, 224, 224);
	m_nBgColor = RGB(255, 255, 255);

	m_hPen = CreatePen(PS_SOLID, 1, m_nColor);
	m_hPenDot = CreatePen(PS_DASH, 1, m_nColor);
	m_hBrush = CreateSolidBrush(m_nBgColor);

	DrawRect(&m_oSize);
//	SetBkMode(m_hDc, TRANSPARENT);
}

CGraphics::CGraphics(HDC hParentDc, int w, int h)
{
	m_oSize.left = m_oSize.top = 0;
	m_oSize.right = w;
	m_oSize.bottom = h;

	m_hWnd = NULL;
	m_hDc = ::CreateCompatibleDC(hParentDc);
	m_hBgBm = ::CreateCompatibleBitmap(hParentDc, m_oSize.right, m_oSize.bottom);
	SelectObject(m_hDc, m_hBgBm);

	SetOrigin(0, 0);

	m_nColor = RGB(0, 0, 0);
	m_nBgColor = RGB(255, 255, 255);

	m_hPen = ::CreatePen(PS_SOLID, 1, m_nColor);
	m_hPenDot = CreatePen(PS_DASH, 1, m_nColor);
	m_hBrush = ::CreateSolidBrush(m_nBgColor);

//	SetBkMode(m_hDc, TRANSPARENT);
}

CGraphics::~CGraphics(void)
{
	::DeleteObject(m_hBrush);
	::DeleteObject(m_hPen);
	::DeleteObject(m_hPenDot);
	::DeleteObject(m_hBgBm);

	if (m_hDc)
		::DeleteDC(m_hDc);
}

void CGraphics::BeginPaint()
{
	if (m_hWnd)
	{
		m_hWndDc = ::BeginPaint(m_hWnd, &m_ps);
		::SetBkMode(m_hDc, TRANSPARENT);
	}
}

void CGraphics::EndPaint()
{
	if (m_hWnd)
	{
		//HDC hWndDc = ::BeginPaint(m_hWnd, &m_ps);

		::BitBlt( m_hWndDc, m_ps.rcPaint.left, m_ps.rcPaint.top
			, m_ps.rcPaint.right - m_ps.rcPaint.left, m_ps.rcPaint.bottom - m_ps.rcPaint.top
			, m_hDc, m_ps.rcPaint.left, m_ps.rcPaint.top, SRCCOPY);

		//printf("%d,%d,%d,%d", m_ps.rcPaint.left, m_ps.rcPaint.right, m_ps.rcPaint.top, m_ps.rcPaint.bottom);
/*		
		::BitBlt( m_hWndDc, m_oSize.left, m_oSize.top
			, m_oSize.right - m_oSize.left, m_oSize.bottom - m_oSize.top
			, m_hDc, 0, 0, SRCCOPY);
*/
		::EndPaint(m_hWnd, &m_ps);
	}
}

const RECT* CGraphics::GetPaintRect()
{
	if (m_hDc)
		return &m_ps.rcPaint;

	return NULL;
}

void CGraphics::SetOrigin(int x, int y)
{
	m_nOriginX = x;
	m_nOriginY = y;
}

void CGraphics::SetColor(int rgb)
{
	m_nColor = rgb;
	::DeleteObject(m_hPen);
	::DeleteObject(m_hPenDot);
	m_hPen = ::CreatePen(PS_SOLID, 1, m_nColor);
	m_hPenDot = ::CreatePen(PS_DOT, 1, m_nColor);
}

void CGraphics::SetBgColor(int rgb)
{
	m_nBgColor = rgb;
	DeleteObject(m_hBrush);
	m_hBrush = CreateSolidBrush(m_nBgColor);
	::SetBkColor(m_hDc, rgb);
}

void CGraphics::DrawRoundRect(const RECT* pRect, int nEllipseWidth, int nEllipseHeight)
{
	::SelectObject(m_hDc, m_hPen);
	::SelectObject(m_hDc, m_hBrush);
	::RoundRect(m_hDc, pRect->left + m_nOriginX, pRect->top + m_nOriginY, pRect->right + m_nOriginX, pRect->bottom + m_nOriginY, nEllipseWidth, nEllipseHeight);
}

void CGraphics::DrawEllipse(const RECT* pRect)
{
	::SelectObject(m_hDc, m_hPen);
	::SelectObject(m_hDc, m_hBrush);
	::Ellipse(m_hDc, pRect->left + m_nOriginX, pRect->top + m_nOriginY, pRect->right + m_nOriginX, pRect->bottom + m_nOriginY);
}

void CGraphics::DrawText(const RECT* pRect, char* pText, int nFormat, BOOL bTransparent /* = NULL */)
{
	if (bTransparent)
	{
		if (TRANSPARENT != ::GetBkMode(m_hDc))
			::SetBkMode(m_hDc, TRANSPARENT);
	}
	else
	{
		if (OPAQUE != ::GetBkMode(m_hDc))
			::SetBkMode(m_hDc, OPAQUE);
	}

	::SetTextColor(m_hDc, m_nColor);
	RECT r = *pRect;
	::OffsetRect(&r, m_nOriginX, m_nOriginY);
	::DrawText(m_hDc, pText, (int)strlen(pText), &r, nFormat);
}

void CGraphics::SetFont(CFont* pFont)
{
	if (pFont)
		::SelectObject(m_hDc, pFont->GetFont());
}

void CGraphics::Copy(const RECT* pDestRect, CGraphics* pSrc, int x, int y)
{
	::BitBlt( m_hDc, pDestRect->left + m_nOriginX, pDestRect->top + m_nOriginY
		, pDestRect->right - pDestRect->left, pDestRect->bottom - pDestRect->top
		, pSrc->m_hDc, x, y, SRCCOPY);
}

void CGraphics::DrawRect(const RECT* pRect)
{
	RECT r = *pRect;
	::OffsetRect(&r, m_nOriginX, m_nOriginY);
	::FillRect(m_hDc, &r, m_hBrush);
}

void CGraphics::DrawLine(int x1, int y1, int x2, int y2)
{
	BOOL r;
	HGDIOBJ old = ::SelectObject(m_hDc, m_hPen);
	r = ::MoveToEx(m_hDc, x1 + m_nOriginX, y1 + m_nOriginY, NULL);
	r = ::LineTo(m_hDc, x2 + m_nOriginX, y2 + m_nOriginY);
}

void CGraphics::DrawLineDot(int x1, int y1, int x2, int y2)
{
	BOOL r;
	HGDIOBJ old = ::SelectObject(m_hDc, m_hPenDot);
	r = ::MoveToEx(m_hDc, x1 + m_nOriginX, y1 + m_nOriginY, NULL);
	r = ::LineTo(m_hDc, x2 + m_nOriginX, y2 + m_nOriginY);
}

CFont::CFont(const char* pFaceName, int nHeight, FontWeight tWeight)
{
	memset(&m_oLogFont, 0, sizeof(m_oLogFont));

	strcpy(m_oLogFont.lfFaceName, pFaceName);
	m_oLogFont.lfHeight = nHeight;
	SetWeight(tWeight);
	m_oLogFont.lfQuality = CLEARTYPE_QUALITY;
}

void CFont::SetFace(const char* pFaceName)
{
	ReleaseHandle();
	strcpy(m_oLogFont.lfFaceName, pFaceName);
}

void CFont::SetHeight(int h)
{
	ReleaseHandle();
	m_oLogFont.lfHeight = h;
}

void CFont::SetWeight(FontWeight tWeight)
{
	ReleaseHandle();
	switch(tWeight)
	{
		case THIN:
			m_oLogFont.lfWeight = 100; break;
		case NORMAL:
			m_oLogFont.lfWeight = 400; break;
		case BOLD:
			m_oLogFont.lfWeight = 700; break;
	}
}

void CFont::SetItalic(BOOL bFlag)
{
	ReleaseHandle();
	m_oLogFont.lfItalic = bFlag;
}

void CFont::SetUnderline(BOOL bFlag)
{
	ReleaseHandle();
	m_oLogFont.lfUnderline = bFlag;
}

void CFont::SetStrikeOut(BOOL bFlag)
{
	ReleaseHandle();
	m_oLogFont.lfStrikeOut = bFlag;
}

HFONT CFont::GetFont()
{
	if (NULL == m_hFont)
		m_hFont = CreateFontIndirect(&m_oLogFont);

	return m_hFont;
}

void CFont::ReleaseHandle()
{
	if (NULL != m_hFont)
	{
		DeleteObject(m_hFont);
		m_hFont = NULL;
	}
}




================================================
FILE: src/Graphics.h
================================================
#pragma once

#include <windows.h>

class CFont;

typedef struct tagSTYLE
{
	int		nColor;
	int		nBgColor;
	int		nTextFormat;	// win32 DrawText macro: DT_...
	CFont*	pFont;
}STYLE;

class CGraphics
{
public:
	CGraphics(HWND hWnd);
	CGraphics(HDC hParentDc, int w, int h);
	~CGraphics(void);

	//void SetErase() { m_bNeedErase = TRUE; };
	void BeginPaint();
	void EndPaint();
	const RECT* GetPaintRect();

	void SetOrigin(int x, int y);
	void DrawRoundRect(const RECT* pRect, int nEllipseWidth, int nEllipseHeight);
	void DrawText(const RECT* pRect, char* pText, int nFormat, BOOL bTransparent = TRUE);
	void SetColor(int rgb);
	void SetBgColor(int rgb);
	void SetFont(CFont* pFont);
	void Copy(const RECT* pDestRect, CGraphics* pSrc, int x, int y);
	void DrawRect(const RECT* pRect);
	void DrawLine(int x1, int y1, int x2, int y2);
	void DrawLineDot(int x1, int y1, int x2, int y2);
	void DrawEllipse(const RECT* pRect);

private:
	HWND			m_hWnd;
	HDC				m_hWndDc;
	HDC				m_hDc;
	PAINTSTRUCT		m_ps;
	HBITMAP			m_hBgBm;

	int				m_nOriginX;
	int				m_nOriginY;

	int				m_nColor;
	int				m_nBgColor;

	HBRUSH			m_hBrush;
	HPEN			m_hPen;
	HPEN			m_hPenDot;

	//BOOL			m_bNeedErase;
	RECT			m_oSize;
};

class CFont
{
public:
	typedef enum { THIN, NORMAL, BOLD } FontWeight;

	CFont(const char* pFaceName, int nSize, FontWeight tWeight);
	~CFont() { ReleaseHandle(); };

	void SetFace(const char* pFaceName);
	void SetHeight(int nSize);
	void SetWeight(FontWeight tWeight);
	void SetItalic(BOOL bFlag);
	void SetUnderline(BOOL bFlag);
	void SetStrikeOut(BOOL bFlag);

	HFONT	GetFont();

private:
	void ReleaseHandle();

	LOGFONT		m_oLogFont;
	HFONT		m_hFont;
};



================================================
FILE: src/LaButton.cpp
================================================
#include "StdAfx.h"
#include "LaButton.h"

CLaButton::CLaButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle/* = BT_NORMAL */, CFont* pFont/* = NULL */)
{
	InitButton(pParent, pText, pRect, nStyle, pFont);
}

void CLaButton::InitButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle, CFont* pFont)
{
	m_nIdxTxt = 0;
	m_pParent = pParent;
	m_oRect = *pRect;
	m_nStyle = nStyle;
	m_pFont = pFont;

	m_nState = BS_UP;
	m_bIsDown = FALSE;
	m_bMouseOver = FALSE;
	m_bMouseHold = FALSE;

	m_pKeyboardEventListener = NULL;
	m_pMouseMoveEventListener = NULL;
	m_pMouseKeyEventListener = NULL;

	m_nWantKeyCode = 0;

	ResolveTextList(pText);
}

CLaButton::~CLaButton(void)
{
	while (0 < m_vText.size())
	{
		delete[] m_vText[m_vText.size() - 1];
		m_vText.pop_back();
	}
}

void CLaButton::AddKeyboardEventListener(IKeyboardEventListener* pListener)
{
	m_pKeyboardEventListener = pListener;
}

void CLaButton::AddMouseMoveEventListener(IMouseMoveEventListener* pListener)
{
	m_pMouseMoveEventListener = pListener;
}

void CLaButton::AddMouseKeyEventListener(IMouseKeyEventListener* pListener)
{
	m_pMouseKeyEventListener = pListener;
}

BOOL CLaButton::IsRelated(int x, int y)
{
	RECT rect = m_oRect;
	BOOL r = IControl::PointInRect(&rect, x, y);
	if (r != m_bMouseOver)
	{
		m_bMouseOver = r;
		m_pParent->Invalidate(&rect);
	}

	return m_bMouseHold || r;
}

void CLaButton::GetRect(RECT* r)
{
	*r = m_oRect;
}

void CLaButton::SetRect(const RECT* r)
{
	m_oRect = *r;
	m_pParent->Invalidate(r);
}

void CLaButton::SetText(const char* pNewText)
{
	while (0 < m_vText.size())
	{
		delete[] m_vText[m_vText.size() - 1];
		m_vText.pop_back();
	}

	ResolveTextList(pNewText);
	m_pParent->Invalidate(&m_oRect);
}

BOOL CLaButton::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	RECT r = m_oRect;
	OffsetRect(&r, -r.left, -r.top);
	
	if (BS_UP == m_nState)
	{
		g->SetBgColor(RGB(255, 255, 255));

		if (m_bMouseOver)
		{
			g->SetColor(RGB(0, 0, 0));
		}
		else
		{
			g->SetColor(RGB(127, 127, 127));
		}
	}
	else
	{
		g->SetColor(RGB(0, 0, 0));
		g->SetBgColor(RGB(240, 240, 240));
	}

	int rw = (r.right - r.left) / 2;
	int rh = (r.bottom - r.top) / 2;
	if (rw > 16) rw = 16;
	if (rh > 16) rh = 16;
	int rd = (rw > rh ? rh : rw);

	g->DrawRoundRect(&r, rd, rd);

	if (m_pFont)
		g->SetFont(m_pFont);

	g->DrawText(&r, m_vText[m_nIdxTxt], DT_VCENTER|DT_CENTER|DT_SINGLELINE);

	return TRUE;
}

void CLaButton::ResolveTextList(const char* pText)
{
	m_nCntTxt = 0;
	for (int i = 0, j; '\0' != pText[i]; i = j, ++m_nCntTxt)
	{
		for (j = i; '\0' != pText[j] && ',' != pText[j]; ++j)
		{
		}

		m_vText.push_back(new char[j - i + 1]);
		strncpy(m_vText[m_nCntTxt], pText + i, j - i);
		m_vText[m_nCntTxt][j - i] = '\0';

		if (',' == pText[j])
			++j;
	}

	m_nIdxTxt = 0;
}

BOOL CLaButton::OnKeyDown(void* owner, int nKeyCode)
{
	if (m_nWantKeyCode == nKeyCode)
	{
		m_nState = BS_DOWN;

		m_pParent->Invalidate(&m_oRect);

		if (m_pKeyboardEventListener)
			m_pKeyboardEventListener->OnKeyDown(this, nKeyCode);

		return TRUE;
	}

	return FALSE;
}

BOOL CLaButton::OnKeyUp(void* owner, int nKeyCode)
{
	if (m_nWantKeyCode == nKeyCode)
	{
		if (BT_LOCKABLE == m_nStyle)
		{
			m_bIsDown = !m_bIsDown;
			m_nState = (m_bIsDown ? BS_DOWN : BS_UP);
		}
		else
			m_nState = BS_UP;

		m_pParent->Invalidate(&m_oRect);

		if (m_pKeyboardEventListener)
			m_pKeyboardEventListener->OnKeyUp(this, nKeyCode);

		OnClick(this);

		return TRUE;
	}

	return FALSE;
}

BOOL CLaButton::OnMouseMove(void* owner, int x, int y)
{
	if (m_pMouseMoveEventListener)
	{
		return m_pMouseMoveEventListener->OnMouseMove(this, x, y);
	}

	return FALSE;
}

BOOL CLaButton::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
	m_bMouseHold = TRUE;
	m_nState = BS_DOWN;
	m_pParent->Invalidate(&m_oRect);

	if (m_pMouseKeyEventListener)
		m_pMouseKeyEventListener->OnMouseKeyDown(this, nMkt, x, y);

	return TRUE;
}

BOOL CLaButton::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
	m_bMouseHold = FALSE;
	if (BT_LOCKABLE == m_nStyle)
	{
		m_bIsDown = !m_bIsDown;
		m_nState = (m_bIsDown ? BS_DOWN : BS_UP);
	}
	else
		m_nState = BS_UP;

	if (m_nCntTxt == ++m_nIdxTxt)
		m_nIdxTxt = 0;

	m_pParent->Invalidate(&m_oRect);

	if (m_pMouseKeyEventListener)
		m_pMouseKeyEventListener->OnMouseKeyUp(this, nMkt, x, y);

	if (IControl::PointInRect(&m_oRect, x + m_oRect.left, y + m_oRect.top))
		OnClick(this);

	return TRUE;
}

BOOL CLaButton::OnClick(void* owner)
{
	BOOL bProcess = FALSE;
	if (m_pKeyboardEventListener)
		bProcess = m_pKeyboardEventListener->OnClick(this);

	if (m_pMouseKeyEventListener && !bProcess)
		bProcess = m_pMouseKeyEventListener->OnClick(this);

	return bProcess;
}



================================================
FILE: src/LaButton.h
================================================
#pragma once

#include "EventManagerWin32.h"

class CLaButton 
	: public IPaintEventControl
	, public IMouseMoveEventControl
	, public IMouseKeyEventControl
	, public IKeyboardEventControl
	, public IUserData
{
public:
	typedef enum { BS_UP, BS_DOWN } ButtonState;
	typedef enum { BT_NORMAL, BT_LOCKABLE } ButtonStyle;

public:
	CLaButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle = BT_NORMAL, CFont* pFont = NULL);
	virtual ~CLaButton(void);

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* pRect);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
	virtual BOOL OnKeyDown(void* owner, int nKeyCode);
	virtual BOOL OnKeyUp(void* owner, int nKeyCode);
	virtual BOOL OnMouseMove(void* owner, int x, int y);
	virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnClick(void* owner);

	virtual void SetRect(const RECT* pRect);
	virtual void SetText(const char* pNewText);

	virtual void SetUserData(void* pUserData) { m_pUserData = pUserData; };
	virtual void* GetUserData() { return m_pUserData; };

	virtual BOOL IsPressed() { return m_bIsDown; };

	void AddKeyboardEventListener(IKeyboardEventListener* pListener);
	void AddMouseMoveEventListener(IMouseMoveEventListener* pListener);
	void AddMouseKeyEventListener(IMouseKeyEventListener* pListener);

	void SetWantKeyCode(int nKeyCode) { m_nWantKeyCode = nKeyCode; };
	int GetWantKeyCode() { return m_nWantKeyCode; };

private:
	IPaintableParent*		m_pParent;
	CFont*		m_pFont;
	vector<char *>		m_vText;
	RECT	m_oRect;
	ButtonStyle		m_nStyle;
	ButtonState		m_nState;
	BOOL	m_bMouseOver;
	int		m_nWantKeyCode;
	BOOL	m_bIsDown;
	BOOL	m_bMouseHold;
	int		m_nIdxTxt;
	int		m_nCntTxt;

	IKeyboardEventListener*		m_pKeyboardEventListener;
	IMouseMoveEventListener*	m_pMouseMoveEventListener;
	IMouseKeyEventListener*		m_pMouseKeyEventListener;

	void*	m_pUserData;

	void InitButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle, CFont* pFont);
	void ResolveTextList(const char* pText);
};


================================================
FILE: src/LaHwControl.cpp
================================================
#include "StdAfx.h"

#include "LaHwControl.h"
//#include "WinIo.h"

CLaHwControl::CLaHwControl(WORD nInitAddr, BYTE bInit)
{
	//m_bInitOk = InitializeWinIo();
	if (m_bInitOk)
	{
	//	m_bInitOk = SetPortVal(nInitAddr, bInit, 1);
	}
}

CLaHwControl::~CLaHwControl()
{
	//if (m_bInitOk)
	//	ShutdownWinIo();
}

BOOL CLaHwControl::OutByte(WORD nAddr, BYTE b)
{
	if (m_bInitOk && m_bState)
	{
	//	return SetPortVal(nAddr, b, 1);
	}

	return FALSE;
}

BOOL CLaHwControl::GetState()
{
	return m_bState;
}

void CLaHwControl::SetState(BOOL bState)
{
	m_bState = bState;
}



================================================
FILE: src/LaHwControl.h
================================================
#pragma once

class CLaHwControl
{
public:
	CLaHwControl(WORD nInitAddr, BYTE bInit);
	~CLaHwControl();

	BOOL OutByte(WORD nAddr, BYTE b);
	BOOL GetState();
	void SetState(BOOL bState);

private:
	BOOL m_bInitOk;
	BOOL m_bState;
};


================================================
FILE: src/LaJournalPanel.cpp
================================================
#include "StdAfx.h"
#include "lajournalpanel.h"

CLaJournalPanel::CLaJournalPanel(IPaintableParent* pParent, const RECT* pRect, const MORSECODE* pMorseList
	, int nMaxShortCount, STYLE* pStyle, IParseEventListener* pParseLsnr)
{
	m_pParent = pParent;
	m_pParseLsnr = pParseLsnr;
	m_oRect = *pRect;
	m_pStyle = pStyle;
	m_pPaintBoard = pParent->NewGraphics(pRect->right - pRect->left, pRect->bottom - pRect->top);
	RECT r;
	SetRect(&r, 0, 0, pRect->right - pRect->left, pRect->bottom - pRect->top);
	m_pPaintBoard->DrawRect(&r);
	//m_pPaintBoard->DrawLine(0, pRect->bottom - pRect->top - 1, pRect->right - pRect->left, pRect->bottom - pRect->top - 1);
	m_nCurrPos = 0;
	m_pMorseParser = new CMorseParser(pMorseList, MORSECODECOUNT, nMaxShortCount, this);
	SetMaxShortCount(nMaxShortCount);
	m_nJitter = 0;
	m_nStateCount = 0;
	m_nStep = 1;
}

CLaJournalPanel::~CLaJournalPanel(void)
{
	delete m_pMorseParser;
	delete m_pPaintBoard;
}

BOOL CLaJournalPanel::IsRelated(int x, int y)
{
	return IControl::PointInRect(&m_oRect, x, y);
}

void CLaJournalPanel::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaJournalPanel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	int w = m_oRect.right - m_oRect.left;
	int h = m_oRect.bottom - m_oRect.top;

	RECT r;
	r.top = 0; r.bottom = h;

	r.left = 0; r.right = w - m_nCurrPos;
	g->Copy(&r, m_pPaintBoard, m_nCurrPos, 0);

	if (0 < m_nCurrPos)
	{
		r.left = w - m_nCurrPos; r.right = w;
		g->Copy(&r, m_pPaintBoard, 0, 0);
	}

	return TRUE;
}

void CLaJournalPanel::Sample(int nState)
{
	// sample filter
	switch(m_nStep)
	{
		case 1:	// init
		{
			if (3 > m_nSampleDiv)
			{
			}
			else if (nState)	// key down
			{
				m_nStateCount = 1;
				m_nStep = 2;
				return;
			}

			if (m_nSampleDiv <= ++m_nStateCount)
			{
				SampleRender(nState);
				m_pMorseParser->Sample(nState);
				m_nStateCount = 0;
			}
			
			break;
		}
		case 2:	// jitter(L) test
		{
			++m_nStateCount;

			if (!nState)
			{
				m_nStep = 3;
			}
			else if (m_nSampleDiv <= m_nStateCount)
			{
				SampleRender(nState);
				m_pMorseParser->Sample(nState);
				m_nStep = 1;
				break;
			}

			return;
		}
		case 3: // jitter(H) test
		{
			if (nState)
			{
				if (m_nSampleDiv <= ++m_nStateCount)
				{
					SampleRender(nState);
					m_pMorseParser->Sample(nState);
					m_nStateCount = 0;
					m_nStep = 1;
					break;
				}
				else
					m_nStep = 2;
			}
			else
			{
				m_nStateCount = 2;
				m_nStep = 1;	// key up
			}

			return;
		}
	}

	m_pParent->Invalidate(&m_oRect);
}

void CLaJournalPanel::SampleRender(int nState)
{
	if (nState)
		m_pPaintBoard->SetColor(m_pStyle->nColor);
	else
		m_pPaintBoard->SetColor(m_pStyle->nBgColor);

	int y = 2;

	m_pPaintBoard->DrawLine(m_nCurrPos, y, m_nCurrPos, y + 5);

	m_pPaintBoard->SetColor(m_pStyle->nBgColor);
	m_pPaintBoard->DrawLine(m_nCurrPos, m_oRect.bottom - m_oRect.top - 16, m_nCurrPos, m_oRect.bottom - m_oRect.top - 1);

	if (++m_nCurrPos >= m_oRect.right - m_oRect.left)
		m_nCurrPos = 0;
}

void CLaJournalPanel::OnWorkOut(void* owner, const MORSECODE* pResult)
{
	char buff[] = { '#', '\0' };

	if (pResult)
		buff[0] = pResult->nAscCode;

	m_pPaintBoard->SetColor(m_pStyle->nColor);
	m_pPaintBoard->SetFont(m_pStyle->pFont);

	RECT r;
	r.right = m_nCurrPos;
	r.left = r.right - 12;
	r.bottom = m_oRect.bottom - m_oRect.top;
	r.top = r.bottom - 16;
	m_pPaintBoard->DrawText(&r, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);

	if (r.left < 0)
	{
		int w = m_oRect.right - m_oRect.left;
		r.right += w;
		r.left += w;
		m_pPaintBoard->DrawText(&r, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
	}

	if (m_pParseLsnr)
		m_pParseLsnr->OnWorkOut(this, pResult);
}

void CLaJournalPanel::SetMaxShortCount(int nCount)
{
	m_nSampleDiv = nCount / 3;
	if (0 == m_nSampleDiv)
		m_nSampleDiv = 1;

	m_pMorseParser->SetMaxShortCount(nCount / m_nSampleDiv);
}


================================================
FILE: src/LaJournalPanel.h
================================================
#pragma once

#include "EventManagerWin32.h"
#include "MorseParser.h"

class CLaJournalPanel
	: public IPaintEventControl
	, public IParseEventListener
{
public:
	CLaJournalPanel(IPaintableParent* pParent, const RECT* pRect, const MORSECODE* pMorseList, int nMaxShortCount, STYLE* pStyle, IParseEventListener* pParseLsnr);
	virtual ~CLaJournalPanel(void);

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
	virtual void OnWorkOut(void* owner, const MORSECODE* pResult);

	virtual void Sample(int nState);
	void SetMaxShortCount(int nCount);

private:
	IPaintableParent*		m_pParent;
	IParseEventListener*	m_pParseLsnr;
	STYLE*		m_pStyle;
	RECT	m_oRect;
	CGraphics*	m_pPaintBoard;
	int		m_nCurrPos;
	int		m_nSampleDiv;
	int		m_nJitter;
	int		m_nStateCount;
	int		m_nStep;

	CMorseParser*	m_pMorseParser;

	void SampleRender(int nState);
};


================================================
FILE: src/LaLabel.cpp
================================================
#include "StdAfx.h"
#include "LaLabel.h"

#include <assert.h>

CLaLabel::CLaLabel(IPaintableParent* pParent, const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName/* = NULL */)
{
	m_pParent = pParent;
	m_oRect = *pRect;
	m_pStyle = pStyle;

	if (pText)
	{
		strncpy(m_vText, pText, MAX_LABEL_TEXT_LEN);
		m_vText[MAX_LABEL_TEXT_LEN] = '\0';
	}
	else
		m_vText[0] = '\0';

	m_hMutex = (pMutexName ? CreateMutex(NULL, FALSE, pMutexName) : NULL);
}

CLaLabel::~CLaLabel(void)
{
}

BOOL CLaLabel::IsRelated(int x, int y)
{
	return IControl::PointInRect(&m_oRect, x, y);
}

void CLaLabel::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaLabel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	RECT r = m_oRect;
	OffsetRect(&r, -r.left, -r.top);
	g->SetBgColor(m_pStyle->nBgColor);
	g->DrawRect(&r);
	g->SetFont(m_pStyle->pFont);
	g->SetColor(m_pStyle->nColor);
	g->DrawText(&r, m_vText, m_pStyle->nTextFormat);

	return TRUE;
}

void CLaLabel::SetText(const char* pText)
{
	if (pText)
	{
		strncpy(m_vText, pText, MAX_LABEL_TEXT_LEN);
		m_vText[MAX_LABEL_TEXT_LEN] = '\0';
	}
	else
		m_vText[0] = '\0';

	m_pParent->Invalidate(&m_oRect);
}

void CLaLabel::GetText(char* pText, int nSize)
{
	strncpy(pText, m_vText, nSize);
}

const char* CLaLabel::GetText()
{
	return (const char *)m_vText;
}

BOOL CLaLabel::PushChar(char ch)
{
	assert(m_hMutex);
	BOOL r = FALSE;

	if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, 1000L))
	{
		for (int i = 0; i < MAX_LABEL_TEXT_LEN; ++i)
		{
			if (!m_vText[i])
			{
				m_vText[i] = ch;
				m_vText[i + 1] = '\0';
				r = TRUE;
				break;
			}
		}
		ReleaseMutex(m_hMutex);
		m_pParent->Invalidate(&m_oRect);
	}

	return r;
}

char CLaLabel::PopChar()
{
	assert(m_hMutex);

	char r = '\0';
	if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, 1000L))
	{
		r = m_vText[0];
		for (int i = 0; i < MAX_LABEL_TEXT_LEN; ++i)
		{
			if (m_vText[i])
				m_vText[i] = m_vText[i + 1];
			else
				break;
		}

		ReleaseMutex(m_hMutex);
		m_pParent->Invalidate(&m_oRect);
	}

	return r;
}


================================================
FILE: src/LaLabel.h
================================================
#pragma once

#include "EventManagerWin32.h"

#define MAX_LABEL_TEXT_LEN		8193

class CLaLabel
	: public IPaintEventControl
{
public:
	CLaLabel(IPaintableParent* pParent, const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName = NULL);
	virtual ~CLaLabel(void);

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);

	virtual void SetText(const char* pText);
	virtual void GetText(char* pText, int nSize);
	virtual const char* GetText();

	virtual BOOL PushChar(char ch);
	virtual char PopChar();

private:
	IPaintableParent*		m_pParent;
	STYLE*		m_pStyle;
	RECT		m_oRect;

	char		m_vText[MAX_LABEL_TEXT_LEN + 1];

	HANDLE		m_hMutex;
};


================================================
FILE: src/LaLine.cpp
================================================
#include "StdAfx.h"
#include "LaLine.h"

CLaLine::CLaLine(IPaintableParent* pParent, int x1, int y1, int x2, int y2)
{
	m_pParent = pParent;

	m_x1 = x1;
	m_x2 = x2;
	m_y1 = y1;
	m_y2 = y2;

	if (x1 > x2) x1 ^= x2 ^= x1 ^= x2;
	if (y1 > y2) y1 ^= y2 ^= y1 ^= y2;

	m_oRect.left = x1;
	m_oRect.top = y1;
	m_oRect.right = x2 + 1;
	m_oRect.bottom = y2 + 1;

	m_x1 -= m_oRect.left;
	m_x2 -= m_oRect.left;
	m_y1 -= m_oRect.top;
	m_y2 -= m_oRect.top;
}

CLaLine::~CLaLine()
{
}

BOOL CLaLine::IsRelated(int x, int y)
{
	return IControl::PointInRect(&m_oRect, x, y);
}

void CLaLine::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaLine::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	g->SetColor(0);
	g->DrawLine(m_x1, m_y1, m_x2, m_y2);

	return TRUE;
}


================================================
FILE: src/LaLine.h
================================================
#pragma once

#include "EventManagerWin32.h"

class CLaLine
	: public IPaintEventControl
{
public:
	CLaLine(IPaintableParent* pParent, int x1, int y1, int x2, int y2);
	virtual ~CLaLine();

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);

private:
	IPaintableParent*		m_pParent;
	RECT	m_oRect;
	int m_x1;
	int m_x2;
	int m_y1;
	int m_y2;

};


================================================
FILE: src/LaNetwork.cpp
================================================
#include "StdAfx.h"
//#include "winsock2.h"
//#include "Ws2tcpip.h"
#include "LaNetwork.h"

#define JOIN_SAFELY(ht)								\
{													\
	if (NULL != ht)									\
	{												\
		DWORD nExitCode_j = -1;						\
		if (GetExitCodeThread(ht, &nExitCode_j))	\
			if (STILL_ACTIVE == nExitCode_j)		\
				WaitForSingleObject(ht, INFINITE);	\
		ht = NULL;									\
	}												\
}

CLaNetwork::CLaNetwork(DWORD nFlgs)
{
	m_nFlgs = nFlgs;
	m_bWsaInit = FALSE;

	m_pEventListener = NULL;
	m_pFrameListener = NULL;

	m_pStbTabHead = NULL;
	m_pDynTabHead = NULL;

	m_hNwRecvThread = m_hNwSendThread = NULL;

	m_nSendInPos = m_nSendOutPos = 0;

	m_socket = NULL;
}

CLaNetwork::~CLaNetwork()
{
	if (m_hNwRecvThread)
	{
		Shutdown();
		ResumeThread(m_hNwRecvThread);
		JOIN_SAFELY(m_hNwRecvThread);
	}

	if (m_hNwSendThread)
	{
		Shutdown();
		ResumeThread(m_hNwSendThread);
		JOIN_SAFELY(m_hNwSendThread);
	}

	if (m_bWsaInit)
	{
		WSACleanup();
		m_bWsaInit = FALSE;
	}

	while(m_pStbTabHead)
	{
		LANWSRCNODE* p = m_pStbTabHead->next;
		delete m_pStbTabHead;
		m_pStbTabHead = p;
	}
}

BOOL CLaNetwork::AppendStbSrcNode(const LANWSRCNODE* pStbSrc)
{
	LANWSRCNODE* p = m_pStbTabHead;

	if (!m_pStbTabHead)
	{
		m_pStbTabHead = new LANWSRCNODE;
		p = m_pStbTabHead;
	}
	else
	{
		while(p->next)
		{
			if (p->base.nAddr == pStbSrc->base.nAddr && p->base.nPort == pStbSrc->base.nPort)
				return FALSE;

			p = p->next;
		}

		p->next = new LANWSRCNODE;
		p = p->next;
	}

	p->base = pStbSrc->base;
	p->attr = pStbSrc->attr;
	p->branch = NULL;
	p->next = NULL;

	return TRUE;
}

BOOL CLaNetwork::AppendNodeByAddr(const sockaddr* pAddr)
{
	if (AF_INET == pAddr->sa_family)
	{
		LANWSRCNODE *pNode = new LANWSRCNODE;
		pNode->base.nAddr = ((sockaddr_in*)pAddr)->sin_addr.S_un.S_addr;
		pNode->base.nPort = ((sockaddr_in*)pAddr)->sin_port;
		pNode->branch = pNode->next = NULL;

		return AppendStbSrcNode(pNode);
	}

	return FALSE;
}

BOOL CLaNetwork::Startup(WORD nPort)
{
	if (m_hNwRecvThread || m_hNwSendThread)
		return TRUE; // only startup once, at the same time

	if (!m_bWsaInit)
	{
		WSADATA wsaData;
		// start up as need
		if (NO_ERROR != WSAStartup(MAKEWORD(2,2), &wsaData))
			return FALSE;

		m_bWsaInit = TRUE;
	}

	m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/*IPPROTO_TCP*/);
	if (INVALID_SOCKET == m_socket)
		return FALSE;

	if (!Bind(nPort))
		return FALSE;

	m_bNeedExit = FALSE;

	m_hNwRecvThread = CreateThread(NULL, 0, NwRecvThreadProc, this, 0, &m_nNwRecvThreadID);
	if (m_hNwRecvThread)
	{
		m_hNwSendThread = CreateThread(NULL, 0, NwSendThreadProc, this, 0, &m_nNwSendThreadID);
		if (m_hNwSendThread)
			return TRUE;

		Shutdown();
		JOIN_SAFELY(m_hNwRecvThread);
	}

	return FALSE;
}

BOOL CLaNetwork::AppendKeyFrame(const LANWPKGKEYFRAME* pFrame)
{
	int nNextPos = m_nSendInPos + 1;
	if (SEND_QUEUE_SIZE == nNextPos)
		nNextPos = 0;
	if (nNextPos == m_nSendOutPos)
		return FALSE;

	m_vSendQ[m_nSendInPos] = *pFrame;
	m_nSendInPos = nNextPos;

	ResumeThread(m_hNwSendThread);

	return TRUE;
}

BOOL CLaNetwork::PickKeyFrame(LANWPKGKEYFRAME* pFrame)
{
	if (IsSendKeyFrameQueueEmpty())
		return FALSE; //empty Q

	*pFrame = m_vSendQ[m_nSendOutPos];
	if (++m_nSendOutPos == SEND_QUEUE_SIZE)
		m_nSendOutPos = 0;

	return TRUE;
}

void CLaNetwork::Shutdown()
{
	m_bNeedExit = TRUE;

	if (m_socket)
	{
		closesocket(m_socket);
		m_socket = NULL;
	}
}

BOOL CLaNetwork::Bind(WORD nPort)
{
	m_nLocalPort = nPort;
	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");
	service.sin_port = htons(m_nLocalPort);

	if (bind(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
	{
		if (m_pEventListener)
			m_pEventListener->OnEvent(NM_BIND_FAILED);

		return FALSE;
	}

	return TRUE;
}

#define NOTEVALIFNEEDEXIT(expr)	if (!owner->m_bNeedExit) expr

DWORD WINAPI CLaNetwork::NwRecvThreadProc(LPVOID pOwner)
{
	CLaNetwork* owner = (CLaNetwork *)pOwner;

	sockaddr	saddr;
	int nFromlen = sizeof(saddr);
	char	sPkgBuff[RECV_BUFF_BYTES];
	int	nFramePos;
	int nReadLen;
	
	LANWPKGHEAD* pLnph;
	LANWPKGKEYFRAME* pLnpkf;
//	LANWPKGSRCFRAME* pLnpsf;
//	LANWPKGTXTFRAME* pLnptf;

	while(!owner->m_bNeedExit)
	{
		nReadLen = recvfrom(owner->m_socket, sPkgBuff, sizeof(sPkgBuff), 0, &saddr, &nFromlen);
		if (SOCKET_ERROR != nReadLen && !owner->m_bNeedExit)
		{
			if (sizeof(LANWPKGHEAD) > nReadLen)
				continue;	// invalid package size

			nFramePos = 0;
			pLnph = (LANWPKGHEAD *)(sPkgBuff + nFramePos);
			if (LA_FLAG != pLnph->nLaFlg)
				continue;	// invalid package head flag

			if (LNPF_KEEPALIVE == pLnph->nPkgFlgs)
			{
				if (sizeof(LANWPKGHEAD) != nReadLen)
					continue;	// invalid keep-alive package size

				// TODO: handle keep alive package
				owner->AppendNodeByAddr(&saddr);
				continue;
			}

			if (LNPF_OFF_LINE == pLnph->nPkgFlgs)
			{
				if (sizeof(LANWPKGHEAD) != nReadLen)
					continue;	// invalid off-line package size

				// TODO: handle off-line package
				continue;
			}
		
			nFramePos += sizeof(LANWPKGHEAD);

			if (LNPF_KEY_FRAME & pLnph->nPkgFlgs)
			{
				if (LNPF_SERVER_FRAME & pLnph->nPkgFlgs)
					continue;	// server must not send key-frame

				if (nFramePos + sizeof(LANWPKGKEYFRAME) > (UINT)nReadLen)
					continue;	// package too small

				pLnpkf = (LANWPKGKEYFRAME *)(sPkgBuff + nFramePos);

				if (owner->m_pFrameListener)
					owner->m_pFrameListener->OnKeyFrame(pLnpkf);

				nFramePos += sizeof(LANWPKGKEYFRAME);
			}

			/*
			if (LNPF_OPERATOR_SOURCE_FRMAE & pLnph->nPkgFlgs)
			{
				if (nFramePos + sizeof(LANWPKGSRCFRAME) > nReadLen)
					continue;	// package too small

				//TODO: handle operator source frame here
				pLnpsf = (LANWPKGSRCFRAME *)(sPkgBuff + nFramePos);
				nFramePos += sizeof(LANWPKGSRCFRAME);

				if (LNPF_OTHER_SDN_FRAME & pLnph->nPkgFlgs)
				{
					if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
						continue;	// package too small

					pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
					nFramePos += sizeof(LANWPKGTXTFRAME);
					if (owner->m_pFrameListener)
						owner->m_pFrameListener->OnSourceFrame(pLnpsf, pLnptf->vText);
				}
				else
				{
					if (owner->m_pFrameListener)
						owner->m_pFrameListener->OnSourceFrame(pLnpsf, NULL);
				}
			}

			if (LNPF_OTHER_SOURCE_FRAME & pLnph->nPkgFlgs)
			{
				if (nFramePos + sizeof(LANWPKGSRCFRAME) < nReadLen)
					continue;	// package too small

				//TODO: handle other source frame here
				pLnpsf = (LANWPKGSRCFRAME *)(sPkgBuff + nFramePos);
				nFramePos += sizeof(LANWPKGSRCFRAME);

				if (LNPF_OTHER_SDN_FRAME & pLnph->nPkgFlgs)
				{
					if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
						continue;	// package too small

					pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
					nFramePos += sizeof(LANWPKGTXTFRAME);
					if (owner->m_pFrameListener)
						owner->m_pFrameListener->OnSourceFrame(pLnpsf, pLnptf->vText);
				}
				else
				{
					if (owner->m_pFrameListener)
						owner->m_pFrameListener->OnSourceFrame(pLnpsf, NULL);
				}
			}

			if (LNPF_TEXT_FRAME & pLnph->nPkgFlgs)
			{
				if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
					continue;	// package too small

				//TODO: handle text frame here
				pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
				if (owner->m_pFrameListener)
					owner->m_pFrameListener->OnTextFrame(pLnptf);

				nFramePos += sizeof(LANWPKGTXTFRAME);
			}
			*/

			if (nFramePos != nReadLen)
			{
				//TODO: handle invalid package here
				continue;
			}
		} // end of if (SOCKET_ERROR != nReadLen && !owner->m_bNeedExit)
		else
		{
			int nErrCode = WSAGetLastError();
		}
	} // end of while(!owner->m_bNeedExit)

	if (owner->m_pEventListener)
		owner->m_pEventListener->OnEvent(NM_EXIT);

	return 0;
}

DWORD WINAPI CLaNetwork::NwSendThreadProc(LPVOID pOwner)
{
	CLaNetwork* owner = (CLaNetwork *)pOwner;
	char sPkgBuff[SEND_BUFF_BYTES];
	LANWPKGHEAD* pPkgHead = (LANWPKGHEAD *)sPkgBuff;
	LANWPKGKEYFRAME* pFrame = (LANWPKGKEYFRAME *)(sPkgBuff + sizeof(LANWPKGHEAD));
	sockaddr_in destAddr;
	destAddr.sin_family = AF_INET;

	while(!owner->m_bNeedExit)
	{
		if (owner->IsSendKeyFrameQueueEmpty())
		{
			SuspendThread(owner->m_hNwSendThread);
			// now send frame immediatly, but may be sleep here for keep alive frame in future
		}
		else
		{
			pPkgHead->nLaFlg = LA_FLAG;
			pPkgHead->nPkgFlgs = LNPF_KEY_FRAME;

			owner->PickKeyFrame(pFrame);

			if (owner->m_pStbTabHead)
				owner->SendKeyFrame(sPkgBuff, sizeof(LANWPKGHEAD) + sizeof(LANWPKGKEYFRAME)
					, &destAddr, owner->m_pStbTabHead);

			/* not supported dynamic node now
			if (owner->m_pDynTabHead)
				owner->SendKeyFrame(sPkgBuff, sizeof(LANWPKGHEAD) + sizeof(LANWPKGKEYFRAME)
					, &destAddr, owner->m_pDynTabHead);
			*/
		}
	}

	return 0;
}

BOOL CLaNetwork::SendKeyFrame(const char* pPkgBuff, int nLen, sockaddr_in* pAddr, const LANWSRCNODE* pHeadNode)
{
	pAddr->sin_addr.s_addr = pHeadNode->base.nAddr;
	pAddr->sin_port = htons(pHeadNode->base.nPort);

	if (SOCKET_ERROR == sendto(m_socket, pPkgBuff, nLen, 0, (SOCKADDR *)pAddr, sizeof(sockaddr_in)))
		return FALSE;

	/* only sent to every branch head
	if (NULL != pHeadNode->branch)
		if (!SendKeyFrame(pPkgBuff, nLen, pAddr, pHeadNode->branch))
			return FALSE;*/

	if (NULL != pHeadNode->next)
		return SendKeyFrame(pPkgBuff, nLen, pAddr, pHeadNode->next);

	return TRUE;
}


================================================
FILE: src/LaNetwork.h
================================================
#pragma once

#define SEND_BUFF_BYTES		128
#define RECV_BUFF_BYTES		128

///ά֡/Ӧ֡
#define LNPF_KEEPALIVE				0x0000
//֡
#define LNPF_KEY_FRAME				0x0001
//ԴϢ֡
#define LNPF_OPERATOR_SOURCE_FRMAE	0x0002
//ԴϢ֡֡
#define LNPF_OPERATOR_SDN_FRMAE		0x0004
//ԴϢ֡
#define LNPF_OTHER_SOURCE_FRAME		0x0020
//ԴϢ֡֡
#define LNPF_OTHER_SDN_FRMAE		0x0040
//ɴֻϢ()
#define LNPF_TEXT_FRAME				0x0100
//֡/תKEY_FRAME
#define LNPF_SERVER_FRAME			0x8000
//
#define LNPF_OFF_LINE				0xffff

#define LNPSF_OFF_LINE				0x0000
#define LNPSF_ON_LINE				0x0001
#define LNPSF_REQUEST				0x0002
//ǿ־
#define LNPSF_SERVER				0x0004
//ǷתSERVER⣬Ҫתյİ
#define LNPSF_BROKER				0x0008

#define NM_BIND_OK					0x0010
#define NM_BIND_FAILED				0x8010
#define NM_EXIT						0x0030

#define LRC_WSASTARTUP_FAILED		0x8001

#define SEND_QUEUE_SIZE				100

#define LA_FLAG						((((WORD)'A') << 8) | ((WORD)'L'))
typedef struct
{
	WORD	nLaFlg;		//'LA'	LA_FLAG
	WORD	nPkgFlgs;	//LNPF_...
} LANWPKGHEAD;

typedef struct
{
	DWORD	nToState : 1;	// 0: off; 1: on
	DWORD	nActTick : 31;	// action tickcount
	DWORD	nReserved;		// 30,000,000
} LANWPKGKEYFRAME;

typedef struct
{
	WORD	nSrcFlgs;	//LNPSF_
	WORD	nPort;
	DWORD	nAddr;
} LANWPKGSRCFRAME;

typedef struct
{
	BYTE	vText[32];
} LANWPKGTXTFRAME;

typedef struct
{
	long	nLastSendto;		// ýڵʱ
	long	nLastRecvFrom;		// Ըýڵʱ
	long	nSendPkgs;			// ܰ
	long	nRecvPkgs;			// ܰ
} LANWSRCNODEATTR;

typedef struct tagLANWSRCNODE
{
	LANWPKGSRCFRAME			base;
	LANWSRCNODEATTR			attr;
	struct tagLANWSRCNODE*	branch;	// ͬһԴϵĽڵ⣬֧ڵֻbranch
	struct tagLANWSRCNODE*	next;	// ͬԴ
} LANWSRCNODE;

class INetworkEventListener
{
public:
	virtual void OnEvent(WORD nMsg) = 0;
};

class INetworkFrameListener
{
public:
	virtual void OnKeyFrame(const LANWPKGKEYFRAME* pFrame) = 0;
	virtual void OnSourceFrame(const LANWPKGSRCFRAME* pFrame, const char* szDomainName) = 0;
	virtual void OnTextFrame(const LANWPKGTXTFRAME* pFrame) = 0;
};

/**
[STABLESOURCE]
node1=[www.layala.org:2009,x,x,x],[...],...
**/
class CLaNetwork
{
public:
	CLaNetwork(DWORD nFlgs);
	~CLaNetwork();

	BOOL Startup(WORD nPort);
	void Shutdown();

	void BindEventListener(INetworkEventListener* pEventListener) { m_pEventListener = pEventListener; };
	void BindFrameListener(INetworkFrameListener* pFrameListener) { m_pFrameListener = pFrameListener; };

	BOOL AppendKeyFrame(const LANWPKGKEYFRAME* pFrame);
	BOOL PickKeyFrame(LANWPKGKEYFRAME* pFrame);
	BOOL IsSendKeyFrameQueueEmpty() { return m_nSendInPos == m_nSendOutPos; };
	//void AppendTextFrameQ(const LANWPKGKEYFRAME* pFrame);

	BOOL AppendStbSrcNode(const LANWSRCNODE* pStbSrc);
	const LANWSRCNODE* GetStbSrcList() { return m_pStbTabHead; };

private:

	// 
	DWORD	m_nFlgs;
	WORD	m_nLocalPort;
	BOOL	m_bNeedExit;

	// CWͶ
	LANWPKGKEYFRAME		m_vSendQ[SEND_QUEUE_SIZE];
	int					m_nSendInPos;	// Ƚ, λ
	int					m_nSendOutPos;	// ȳ, λ, InPosʱΪ

	// ̬ڵ
	LANWSRCNODE*		m_pStbTabHead;

	// ̬ڵ
	LANWSRCNODE*		m_pDynTabHead;

	INetworkEventListener*	m_pEventListener;
	INetworkFrameListener*	m_pFrameListener;

	BOOL		m_bWsaInit;
	HANDLE		m_hNwRecvThread;
	HANDLE		m_hNwSendThread;
	DWORD		m_nNwRecvThreadID;
	DWORD		m_nNwSendThreadID;
	SOCKET		m_socket;

	BOOL Bind(WORD nPort);
	static DWORD WINAPI NwRecvThreadProc(LPVOID pOwner);
	static DWORD WINAPI NwSendThreadProc(LPVOID pOwner);
	BOOL SendKeyFrame(const char* pPkgBuff, int nLen, sockaddr_in* pAddr, const LANWSRCNODE* pHeadNode);
	BOOL AppendNodeByAddr(const sockaddr* pAddr);
};


================================================
FILE: src/LaSpectrogram.cpp
================================================
#include "StdAfx.h"
#include "LaSpectrogram.h"

CLaSpectrogram::CLaSpectrogram(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSamples)
{
	m_nBorderWidth = 1;
	m_pFont = new CFont("Arial", 8, CFont::THIN);
	m_pParent = pParent;
	m_oRect = *pRect;
	int w = m_oRect.right - m_oRect.left;
	int h = m_oRect.bottom - m_oRect.top;
	SetRect(&m_oPaintRect, m_nBorderWidth, m_nBorderWidth, w - m_nBorderWidth, h - m_nBorderWidth);

	m_nBgColor = 0x000000;
	m_nFrColor = 0xffff00;

	m_pPaintBoard = pParent->NewGraphics(m_oPaintRect.right - m_oPaintRect.left, m_oPaintRect.bottom - m_oPaintRect.top);

	m_nAnalyzeSamples = nAnalyzeSamples;

	m_bFraze = FALSE;

	h = m_oPaintRect.bottom - m_oPaintRect.top;
	m_rPaintScale = (float)(h) / (float)m_nAnalyzeSamples;
	m_rPaintScaleNext = m_rPaintScale;
	m_rPaintIdx = 0;
	m_nCurrPos = 0;
	m_vFilterBuf = new float[h];
	m_nPhases = -1;
	m_nPhasesDiv = 512 / m_nAnalyzeSamples;
	m_bOrgSize = FALSE;
}

CLaSpectrogram::~CLaSpectrogram(void)
{
	delete[] m_vFilterBuf;
	delete m_pFont;
	delete m_pPaintBoard;
}

BOOL CLaSpectrogram::Initialize()
{
	return TRUE;
}

BOOL CLaSpectrogram::IsRelated(int x, int y)
{
	return IControl::PointInRect(&m_oRect, x, y);
}

void CLaSpectrogram::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaSpectrogram::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	int w = m_oPaintRect.right - m_oPaintRect.left;
	int h = m_oPaintRect.bottom - m_oPaintRect.top;

	RECT r = m_oPaintRect;
	r.right -= (m_nCurrPos + 1);

	if (m_nCurrPos < w - 1)
	{
		g->Copy(&r, m_pPaintBoard, m_nCurrPos + 1, 0);
	}

	r.left = r.right; r.right = r.left + m_nCurrPos + 1;
	g->Copy(&r, m_pPaintBoard, 0, 0);

	w = m_oRect.right - m_oRect.left - 1;
	h = m_oRect.bottom - m_oRect.top - 1;
	g->SetColor(0x808080);
	g->DrawLine(0, 0, 0, h + 1);
	g->DrawLine(0, 0, w + 1, 0);
	g->SetColor(0xffffff);
	g->DrawLine(w, 0, w, h + 1);
	g->DrawLine(0, h, w + 1, h);

	return TRUE;
}

short int CLaSpectrogram::OnEncodeFilter(float val, int i)
{
	if (0 == i)
	{
		if (++m_nPhases > m_nPhasesDiv)
		{
			Refresh();
			if (++m_nCurrPos >= m_oPaintRect.right - m_oPaintRect.left)
				m_nCurrPos = 0;

			m_nPhases = 0;
			m_rPaintScale = m_rPaintScaleNext;
		}

		m_rPaintIdx = 0.0f;
	}

	float currIdx = m_rPaintIdx;
	m_rPaintIdx += m_rPaintScale;
	float w = abs(val) * m_rPaintScale / 256.0f * m_rBrightnessScale;
	int j = (int)currIdx + 1;

	if (j < m_oPaintRect.bottom - m_oPaintRect.top)
	{
		for (; j <= (int)m_rPaintIdx; currIdx = j++)
		{
			m_vFilterBuf[j - 1] += w * (j - currIdx);
		}

		m_vFilterBuf[j - 1] += w * (m_rPaintIdx - currIdx);
	}


	return val;
}

void CLaSpectrogram::SetBrightness(float scale)
{
	m_rBrightnessScale = pow(10.0f, scale / 20.0f);
}

short int CLaSpectrogram::OnDecodeFilter(float val, int i)
{
	return val;
}

/***
 * ˢ¿ؼػߣȡƵݣ
 *
 */
BOOL CLaSpectrogram::Refresh()
{
	int h = m_oPaintRect.bottom - m_oPaintRect.top;
	int lval = min(abs(m_vFilterBuf[0]), 255);
	int lpos = 0, i;

	for (i = lpos + 1; i < h; ++i)
	{
		if (lval != m_vFilterBuf[i])
		{
			m_pPaintBoard->SetColor(RGB(lval, lval, lval));
			m_pPaintBoard->DrawLine(m_nCurrPos, m_oPaintRect.bottom - (lpos + m_oPaintRect.top) - 1, m_nCurrPos, m_oPaintRect.bottom - (i + m_oPaintRect.top) - 1);
			lval = min(abs(m_vFilterBuf[i]), 255);
			lpos = i;
		}

		m_vFilterBuf[i] = 0;
	}

	if (i - 1 != lpos)
	{
		m_pPaintBoard->SetColor(RGB(0, 0, 0));
		m_pPaintBoard->DrawLine(m_nCurrPos, lpos, m_nCurrPos, h);
	}

	m_vFilterBuf[0] = 0;
	//RECT r = m_oPaintRect;
	//OffsetRect(&r, m_oRect.left, m_oRect.top);
	m_pParent->Invalidate(&m_oRect);

	return TRUE;
}

BOOL CLaSpectrogram::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
	switch(nMkt)
	{
		case MouseKeyType::RBUTTON:
		{
			if (m_bOrgSize = !m_bOrgSize)
			{
				m_rPaintScaleNext = 1.0f;
			}
			else
			{
				m_rPaintScaleNext = (m_oPaintRect.bottom - m_oPaintRect.top) / (float)m_nAnalyzeSamples;
			}
			return TRUE;
		}
		case MouseKeyType::LBUTTON:
		{

			return TRUE;
		}
	}

	return FALSE;
}

BOOL CLaSpectrogram::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
	return FALSE;
}

void CLaSpectrogram::SetBackgroundColor(int nColor)
{
	m_nBgColor = nColor;
}



================================================
FILE: src/LaSpectrogram.h
================================================
#pragma once

#include "EventManagerWin32.h"
#include "FFT.h"
#include "dsound.h"

//log(32768)
//#define LOG_SAMPLE_RANGE	4.51545	
#define LOG_SAMPLE_RANGE	4.51545f

class ICwEventListener;

class CLaSpectrogram
	: public IPaintEventControl
	, public IMouseKeyEventControl
	, public IFilterDFT<short int, float>
{
public:
	CLaSpectrogram(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSample);
	~CLaSpectrogram(void);

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);

	virtual BOOL Initialize();
	virtual BOOL Refresh();

	virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnClick(void* owner) { return FALSE; };

	virtual short int OnEncodeFilter(float val, int i);
	virtual short int OnDecodeFilter(float val, int i);

	void SetBackgroundColor(int nColor);
	void SetFrontColor(int nColor);

	void SetBrightness(float scale);

private:
	int AnalyzeData();
	DWORD GetSyncPos(short int* pBuff, DWORD nBuffSize);

	void DrawRuler();
	void DrawBorder();
	void DrawGrid();

	IPaintableParent*		m_pParent;
	CFont*		m_pFont;
	RECT		m_oRect;	// by parent
	RECT		m_oPaintRect;	// by self
	CGraphics*	m_pPaintBoard;
	int			m_nAnalyzeSamples;

	int			m_nBorderWidth;

	int			m_nBgColor;
	int			m_nFrColor;

	BOOL		m_bFraze;

	float*		m_vFilterBuf;
	float		m_rPaintIdx;
	int			m_nCurrPos;
	float		m_rPaintScale;	// m_nAnalyzeSamples / canvos height
	float		m_rPaintScaleNext;
	int			m_nPhases;
	int			m_nPhasesDiv;
	float		m_rBrightnessScale;
	BOOL		m_bOrgSize;
};


================================================
FILE: src/LaTuner.cpp
================================================
#include "StdAfx.h"
#include "latuner.h"
#include "FFT.h"

CLaTuner::CLaTuner(IPaintableParent* pParent, const char* pText, const RECT* pRect, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont)
{
	InitButton(pParent, pRect, pText, nScaleL, nScaleR, nScale, pFont);
}

CLaTuner::~CLaTuner()
{
}

void CLaTuner::SetScale(LASCALE nScale)
{
	m_nScaleCurr = nScale;
	m_pParent->Invalidate(&m_oRect);
}

void CLaTuner::InitButton(IPaintableParent* pParent, const RECT* pRect, const char* pText, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont)
{
	m_nIdxTxt = 0;
	m_pParent = pParent;
	m_oRect = *pRect;
	m_pFont = pFont;

	m_nScaleL = nScaleL;
	m_nScaleR = nScaleR;
	m_nScaleDiv = (nScaleR - nScaleL) / 256;
	m_nScaleDivD = 0;
	m_nScaleCurr = nScale;

	m_bMouseOver = FALSE;
	m_bRbuttonHold = FALSE;
	m_bLbuttonHold = FALSE;

//	m_pKeyboardEventListener = NULL;
	m_pMouseMoveEventListener = NULL;
	m_pMouseKeyEventListener = NULL;
	m_pTunerEventListener = NULL;

	ResolveTextList(pText);
	
	((CEventDispatcherWin32 *)pParent)->AddTimerEventControl(this, LA_TUNER_HEARTBEAT_TIMER_ID, 60);
}

BOOL CLaTuner::IsRelated(int x, int y)
{
	RECT rect = m_oRect;
	BOOL r = IControl::PointInRect(&rect, x, y);
	if (r != m_bMouseOver)
	{
		m_bMouseOver = r;
		m_pParent->Invalidate(&rect);
	}

	return m_bRbuttonHold || m_bLbuttonHold || r;
}

void CLaTuner::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaTuner::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	char buff[16];
	RECT a = m_oRect;
	OffsetRect(&a, -a.left, -a.top);
	
	g->SetBgColor(RGB(255, 255, 255));

	if (m_bMouseOver)
	{
		g->SetColor(RGB(0, 0, 0));
	}
	else
	{
		g->SetColor(RGB(127, 127, 127));
	}

	if (m_pFont)
		g->SetFont(m_pFont);

	RECT t = a;
	int r = (int)((a.bottom < a.right ? a.bottom : a.right) / 3.2f);
	int ox = a.right / 2;
	int oy = a.bottom / 2;
	t.left = ox - r;
	t.right = ox + r;
	t.top = oy - r;
	t.bottom = oy + r;

	g->DrawEllipse(&t);
	if (m_bMouseOver || m_bLbuttonHold || m_bRbuttonHold)
	{
		if (abs(m_nScaleR - m_nScaleL) > 20)
			sprintf(buff, "%0.0f", m_nScaleCurr);
		else if (abs(m_nScaleR - m_nScaleL) > 2)
			sprintf(buff, "%0.1f", m_nScaleCurr);
		else
			sprintf(buff, "%0.2f", m_nScaleCurr);

		g->DrawText(&t, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
	}

	int nScaleLen = r / 5;
	int nSplitWidth = nScaleLen / 2;
	float rx, ry;
	int nScaleCount = 10;
	float srad = 0.75f / nScaleCount;
	for (int i = 0; i <= nScaleCount; ++i)
	{
		rx = cosf(2 * PI * (i * srad + 0.375f));
		ry = sinf(2 * PI * (i * srad + 0.375f));

		if (0 == i || i == nScaleCount)
		{
			int tx = (int)(ox + (r + nScaleLen * 2 + nSplitWidth) * rx);
			int ty = (int)(oy + (r + nScaleLen * 2 + nSplitWidth) * ry);
			g->DrawLine((int)(ox + (r + nSplitWidth) * rx), (int)(oy + (r + nSplitWidth) * ry)
				, tx, ty);
			
			g->DrawLine(tx, ty, 0 == i ? 0 : a.right, ty);
		}
		else
		{
			g->DrawLine((int)(ox + (r + nSplitWidth) * rx), (int)(oy + (r + nSplitWidth) * ry)
				, (int)(ox + (r + nScaleLen + nSplitWidth) * rx), (int)(oy + (r + nScaleLen + nSplitWidth) * ry));
		}
	}

	t.left = 0;
	t.right = ox - r;
	t.top = 0;
	t.bottom = oy + r + 0;
	sprintf(buff, "%0.0f", m_nScaleL);
	g->DrawText(&t, buff, DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);

	t.left = ox + r + 2;
	t.right = a.right;
	sprintf(buff, "%0.0f", m_nScaleR);
	g->DrawText(&t, buff, DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);

	LASCALE rd = 2 * PI * 0.75f * (m_nScaleCurr - m_nScaleL) / (m_nScaleR - m_nScaleL) + PI * 0.75f;
	int px = (int)((r - 8) * cosf(rd) + ox);
	int py = (int)((r - 8) * sinf(rd) + oy);
	t.left = px - 3;
	t.right = px + 3;
	t.top = py - 3;
	t.bottom = py + 3;

	g->DrawEllipse(&t);

	g->DrawText(&a, m_vText[m_nIdxTxt], DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);

	return TRUE;
}

BOOL CLaTuner::OnMouseMove(void* owner, int x, int y)
{
	return FALSE;
}

BOOL CLaTuner::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
	switch(nMkt)
	{
	case LBUTTON:
		m_bLbuttonHold = TRUE; break;
	case RBUTTON:
		m_bRbuttonHold = TRUE; break;
	default:
		return FALSE;
	}

	m_nScaleDivD = 0;

	return TRUE;
}

BOOL CLaTuner::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
	switch(nMkt)
	{
	case LBUTTON:
		m_bLbuttonHold = FALSE; break;
	case RBUTTON:
		m_bRbuttonHold = FALSE; break;
	default:
		return FALSE;
	}

	m_nScaleDivD = 0;

	m_pParent->Invalidate(&m_oRect);

	return TRUE;
}

BOOL CLaTuner::OnTimer(void* owner, int nTimerId)
{
	if (LA_TUNER_HEARTBEAT_TIMER_ID == nTimerId
		&& m_bMouseOver)
	{
		if (m_bRbuttonHold)
			m_nScaleCurr += (m_nScaleDiv + m_nScaleDivD);
		else if (m_bLbuttonHold)
			m_nScaleCurr -= (m_nScaleDiv + m_nScaleDivD);
		else
			return FALSE;

		m_nScaleDivD += m_nScaleDiv;

		if (m_nScaleDiv < 0)
		{
			if (m_nScaleCurr < this->m_nScaleR)
				m_nScaleCurr = m_nScaleR;
			else if (m_nScaleCurr > this->m_nScaleL)
				m_nScaleCurr = m_nScaleL;
		}
		else
		{
			if (m_nScaleCurr < this->m_nScaleL)
				m_nScaleCurr = m_nScaleL;
			else if (m_nScaleCurr > this->m_nScaleR)
				m_nScaleCurr = m_nScaleR;
		}
		
		m_pParent->Invalidate(&m_oRect);

		if (m_pTunerEventListener)
			m_pTunerEventListener->OnTune(this, m_nScaleCurr);

		return TRUE;
	}

	return FALSE;
}

/*void CLaTuner::AddKeyboardEventListener(IKeyboardEventListener* pListener)
{
	m_pKeyboardEventListener = pListener;
}*/

void CLaTuner::AddMouseMoveEventListener(IMouseMoveEventListener* pListener)
{
	m_pMouseMoveEventListener = pListener;
}

void CLaTuner::AddMouseKeyEventListener(IMouseKeyEventListener* pListener)
{
	m_pMouseKeyEventListener = pListener;
}

void CLaTuner::AddTunerEventListener(ITunerEventListener* pListener)
{
	m_pTunerEventListener = pListener;
}

void CLaTuner::ResolveTextList(const char* pText)
{
	m_nCntTxt = 0;
	for (int i = 0, j; '\0' != pText[i]; i = j, ++m_nCntTxt)
	{
		for (j = i; '\0' != pText[j] && ',' != pText[j]; ++j)
		{
		}

		m_vText.push_back(new char[j - i + 1]);
		strncpy(m_vText[m_nCntTxt], pText + i, j - i);
		m_vText[m_nCntTxt][j - i] = '\0';

		if (',' == pText[j])
			++j;
	}

	m_nIdxTxt = 0;
}



================================================
FILE: src/LaTuner.h
================================================
#pragma once

#include "EventManagerWin32.h"

#define LA_TUNER_HEARTBEAT_TIMER_ID		10060
typedef float	LASCALE;

class ITunerEventListener
{
public:
	virtual BOOL OnTune(void* owner, LASCALE nScale) = 0;
};

class CLaTuner
	: public IPaintEventControl
	, public IMouseMoveEventControl
	, public IMouseKeyEventControl
	, public ITimerEventControl
{
public:
	CLaTuner(IPaintableParent* pParent, const char* pText, const RECT* pRect, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont);
	virtual ~CLaTuner();

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
	virtual BOOL OnMouseMove(void* owner, int x, int y);
	virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnTimer(void* owner, int nTimerId);
	virtual BOOL OnClick(void* owner) { return FALSE; };

//	void AddKeyboardEventListener(IKeyboardEventListener* pListener);
	void AddMouseMoveEventListener(IMouseMoveEventListener* pListener);
	void AddMouseKeyEventListener(IMouseKeyEventListener* pListener);
	void AddTunerEventListener(ITunerEventListener* pListener);
	void SetScale(LASCALE nScale);
	LASCALE GetScale() { return m_nScaleCurr; };

private:
	IPaintableParent*		m_pParent;

	CFont*		m_pFont;
	vector<char *>		m_vText;
	RECT	m_oRect;
	LASCALE	m_nScaleL;
	LASCALE	m_nScaleR;
	LASCALE	m_nScaleDiv;
	LASCALE	m_nScaleDivD;
	LASCALE	m_nScaleCurr;

	BOOL	m_bMouseOver;
	BOOL	m_bRbuttonHold;
	BOOL	m_bLbuttonHold;
	int		m_nIdxTxt;
	int		m_nCntTxt;

//	IKeyboardEventListener*		m_pKeyboardEventListener;
	IMouseMoveEventListener*	m_pMouseMoveEventListener;
	IMouseKeyEventListener*		m_pMouseKeyEventListener;
	ITunerEventListener*		m_pTunerEventListener;

	void*	m_pUserData;

	void InitButton(IPaintableParent* pParent, const RECT* pRect, const char* pText, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont);
	void ResolveTextList(const char* pText);
};


================================================
FILE: src/LaWaveCapture.cpp
================================================
#include "StdAfx.h"
#include "lawavecapture.h"
#include "sinsound.h"

CLaWaveCapture::CLaWaveCapture(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSamples, IFilterDFT<short int, float>* pNextFilter, ICwEventListener* pCwEventListener/* = NULL */)
{
	m_bRulerInvalid = TRUE;
	m_nBorderWidth = 1;
	m_nRularH = 9;
	m_nRularV = 16;
	m_pFont = new CFont("Arial", 8, CFont::THIN);
	m_nWaveState = WAVE_ORIGINAL;
	m_nDctState = DCT_LOG10_FLOAT;
	m_nWaveStateTip = 0;
	m_nDctStateTip = 0;
	m_pParent = pParent;
	m_oRect = *pRect;
	int w = m_oRect.right - m_oRect.left;
	int h = m_oRect.bottom - m_oRect.top;
	SetRect(&m_oPaintRect, m_nBorderWidth, m_nBorderWidth, w - m_nRularV - m_nBorderWidth, h - m_nRularH - m_nBorderWidth);
	SetRect(&m_oRulerRectH, m_nBorderWidth, h - m_nRularH - m_nBorderWidth, w - m_nRularV - m_nBorderWidth, h - m_nBorderWidth);
	SetRect(&m_oRulerRectV, m_oPaintRect.right, m_oPaintRect.top, w - m_nBorderWidth, h - m_nRularH - m_nBorderWidth);
	m_nRulerWidthH = w - m_nRularV - m_nBorderWidth * 2;
	m_nRulerWidthV = h - m_nRularH - m_nBorderWidth * 2;
	m_nRulerGridsV = (100 < m_nRulerWidthV ? 8 : 4);
	m_nRulerDbMax = 80;

	m_nBgColor = 0x000000;
	m_nWaveColor = 0x00f000;
	m_nFreqAnaColor = 0x808080;
	m_nFloatColor = 0xf0f0f0;
	m_nRulerColorH = 0x008000;
	m_nRulerColorV = 0x008080;
	m_nGridColorH = 0x000080;
	m_nGridColorV = 0x004040;
	m_nEnabledColor = 0x00f000;
	m_nDisabledColor = 0x808080;

	m_pPaintBoard = pParent->NewGraphics(pRect->right - pRect->left, pRect->bottom - pRect->top);

	m_pCwEventListener = pCwEventListener;

	m_pDsCap = NULL;
	m_pDsCapBuff = NULL;

	memset(&m_oFormat, 0, sizeof(m_oFormat)); 
	m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
	m_oFormat.nChannels = 1;
	m_oFormat.nSamplesPerSec = nSamplePerSec;
	m_oFormat.wBitsPerSample = 16;
	m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
	m_oFormat.nBlockAlign = m_oFormat.wBitsPerSample / 8 * m_oFormat.nChannels;
	m_oFormat.cbSize = 0;

	memset(&m_oCaptureBufferDesc, 0, sizeof(m_oCaptureBufferDesc));
	m_oCaptureBufferDesc.dwSize = sizeof(m_oCaptureBufferDesc);
	m_oCaptureBufferDesc.dwFlags = 0;
	m_oCaptureBufferDesc.dwBufferBytes = m_oFormat.nAvgBytesPerSec * 2;	// 2 sec buffer
	m_oCaptureBufferDesc.lpwfxFormat = &m_oFormat;
	m_oCaptureBufferDesc.dwFXCount = 0;
	m_oCaptureBufferDesc.lpDSCFXDesc = NULL;

	m_nAnalyzeSamples = nAnalyzeSamples;
	m_pWavBuff = new short int[m_nAnalyzeSamples * 2];
	m_pDctBuff = new short int[m_nAnalyzeSamples];
	m_pFreqRuler = new short int[m_nRulerWidthH];
	m_pFloatLine = new short int[m_nAnalyzeSamples];
	m_pFloatClear = new short int[m_nAnalyzeSamples];
	memset(m_pFloatLine, 0, sizeof(short int) * m_nAnalyzeSamples);
	memset(m_pFloatClear, 0, sizeof(short int) * m_nAnalyzeSamples);
	//m_nFloatClear = 0;

	//DrawRuler();
	DrawBorder();

	m_nRecvThreshold = (short int)(32768 * 0.5l);
	m_nRecvFreqStart = 850;
	m_nRecvFreqEnd = 1250;

//	m_pFft = new TCosDFT<short int, float>(m_nAnalyzeSamples, this);
	m_pFft = new TFastFT<short int, float>(m_nAnalyzeSamples, this);
	m_pNextFilter = pNextFilter;

	m_bFraze = FALSE;

	InitTestBuffer();
	m_nTestIndex = 0;
}

CLaWaveCapture::~CLaWaveCapture(void)
{
	delete m_pFont;
	delete m_pPaintBoard;

	if (NULL != m_pDsCap)
	{
		if (NULL != m_pDsCapBuff)
		{
			m_pDsCapBuff->Release();
			m_pDsCapBuff = NULL;
		}

		m_pDsCap->Release();
		m_pDsCap = NULL;
	}

	delete[] m_pWavBuff;
	delete[] m_pDctBuff;
	delete[] m_pFreqRuler;
	delete[] m_pFloatLine;
	delete[] m_pFloatClear;

	delete[] m_pTestBuff;
}

void CLaWaveCapture::SetThresholdLevel(double rThresholdLevel)
{
	m_nRecvThreshold = (short int)(32768 * rThresholdLevel);
}

void CLaWaveCapture::SetFreqRange(int nLowFreq, int nHighFreq)
{
	m_nRecvFreqStart = nLowFreq;
	m_nRecvFreqEnd = nHighFreq;
}

void CLaWaveCapture::DrawRuler()
{
	m_bRulerInvalid = FALSE;
	double rTotalLogNum = log10(16000.0l) - 2;
	for (int i = 0; i < m_nRulerWidthH; ++i)
	{
		m_pFreqRuler[i] = (short int)pow(10, 2 + (i * rTotalLogNum / m_nRulerWidthH));
	}

	m_pPaintBoard->SetBgColor(m_nBgColor);
	m_pPaintBoard->DrawRect(&m_oRulerRectH);
	m_pPaintBoard->SetColor(m_nRulerColorH);
	m_pPaintBoard->DrawLine(m_oRulerRectH.left, m_oRulerRectH.top, m_oRulerRectH.right, m_oRulerRectH.top);
	m_pPaintBoard->SetFont(m_pFont);
	double d = m_nRulerWidthH / rTotalLogNum;
	RECT r = m_oRulerRectH;
//	RECT tr;
	char grad[8];
	r.top += 1;
	for (int i = 0; i < rTotalLogNum; ++i)
	{
		r.left = (int)(d * i);

		if (0 == i)
			sprintf(grad, "%.0lfHz", pow(10.0, i + 2));
		else if (3 > i + 2)
			sprintf(grad, "%.0lf", pow(10.0, i + 2));
		else
			sprintf(grad, "%.0lfK", pow(10.0, i + 2) / 1000);

		//m_pPaintBoard->SetColor(RGB(192, 192, 192));
		r.left += 2;
		m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
		r.left -= 2;
		//m_pPaintBoard->SetColor(RGB(224, 224, 224));
		m_pPaintBoard->DrawLine(r.left, 0 == i ? 0 : m_oRulerRectH.top + 1, r.left, m_oRulerRectH.bottom - 1);

		if (4 > i)
		{
			for (int j = 2; j < 6 && r.left < m_nRulerWidthH; ++j)
			{
				r.left = (int)(d * (i + log10((double)j)));

				sprintf(grad, "%d", j);

//				m_pPaintBoard->SetColor(m_nFreqAnaColor);
				r.left += 2;
				m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
				r.left -= 2;
//				m_pPaintBoard->SetColor(m_nFreqAnaColor);
				m_pPaintBoard->DrawLine(r.left, m_oRulerRectH.top + 1, r.left, m_oRulerRectH.bottom - 2);
			}
		}
	}

	// draw rular-V
	m_pPaintBoard->SetBgColor(m_nBgColor);
	m_pPaintBoard->DrawRect(&m_oRulerRectV);
	m_pPaintBoard->DrawLine(m_oRulerRectV.left, m_oRulerRectV.top, m_oRulerRectV.left, m_oRulerRectV.bottom);

	switch(m_nDctState)
	{
	case DCT_LOG10_FLOAT:
	case DCT_LOG10:
		m_pPaintBoard->SetColor(m_nRulerColorV);
		r = m_oRulerRectV;
		r.bottom = r.top + m_nRularV;
		m_pPaintBoard->DrawText(&r, "dB", DT_CENTER);
		//r.top -= 3;

		for (int i = 1; i <= m_nRulerGridsV; ++i)
		{
			r.top = m_oRulerRectV.top + i * m_nRulerWidthV / m_nRulerGridsV - 3;
			r.bottom = r.top + m_nRularV;
			//OffsetRect(&r, 0, m_nRulerWidthV / m_nRulerGridsV);
			sprintf(grad, "-%d", i * m_nRulerDbMax / m_nRulerGridsV);
			m_pPaintBoard->DrawText(&r, grad, DT_CENTER);
		}
		break;
	case DCT_LINEAR_FLOAT:
	case DCT_LINEAR:
		m_pPaintBoard->SetColor(m_nRulerColorV);
		r = m_oRulerRectV;
		r.bottom = m_nRularV;
		m_pPaintBoard->DrawText(&r, "%", DT_CENTER);
		r.top -= 3;

		for (int i = 2; i <= m_nRulerGridsV; i+=2)
		{
			OffsetRect(&r, 0, m_nRulerWidthV * 2 / m_nRulerGridsV);
			sprintf(grad, "%d", 100 - i * 100 / m_nRulerGridsV);
			m_pPaintBoard->DrawText(&r, grad, DT_CENTER);
		}
		break;
	}
}

void CLaWaveCapture::DrawBorder()
{
	int w = m_oRect.right - m_oRect.left - 1;
	int h = m_oRect.bottom - m_oRect.top - 1;
	m_pPaintBoard->SetColor(0x808080);
	m_pPaintBoard->DrawLine(0, 0, 0, h + 1);
	m_pPaintBoard->DrawLine(0, 0, w + 1, 0);
	m_pPaintBoard->SetColor(0xffffff);
	m_pPaintBoard->DrawLine(w, 0, w, h + 1);
	m_pPaintBoard->DrawLine(0, h, w + 1, h);
}

void CLaWaveCapture::DrawGrid()
{
	m_pPaintBoard->SetColor(m_nGridColorV);
	for (int i = 1; i < m_nRulerGridsV; ++i)
	{
		m_pPaintBoard->DrawLineDot(m_oPaintRect.left, m_nBorderWidth + i * m_nRulerWidthV / m_nRulerGridsV, m_oPaintRect.right, m_nBorderWidth + i * m_nRulerWidthV / m_nRulerGridsV);
	}
}
BOOL CLaWaveCapture::Initialize()
{
	m_nNextPeriodStartPos = -1;

	if (FAILED(DirectSoundCaptureCreate8(NULL, &m_pDsCap, NULL)))
		return FALSE;

	if (FAILED(m_pDsCap->CreateCaptureBuffer(&m_oCaptureBufferDesc, &m_pDsCapBuff, NULL)))
		return FALSE;

	return FAILED(m_pDsCapBuff->Start(DSCBSTART_LOOPING));
}

BOOL CLaWaveCapture::IsRelated(int x, int y)
{
	return IControl::PointInRect(&m_oRect, x, y);
}

void CLaWaveCapture::GetRect(RECT* r)
{
	*r = m_oRect;
}

BOOL CLaWaveCapture::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
	int w = m_oRect.right - m_oRect.left;
	int h = m_oRect.bottom - m_oRect.top;

	RECT r;
	r.top = 0; r.bottom = h;
	r.left = 0; r.right = w;
	g->Copy(&r, m_pPaintBoard, 0, 0);

	return TRUE;
}

#define TRANSFORM_SAMPLE(f, t)				\
	int x = f;								\
	x <<= (m_nWaveState - WAVE_ORIGINAL);	\
	if (x > 32767)							\
		x = 32767;							\
	else if (x < -32767)					\
		x = -32767;							\
	t = m_oPaintRect.top + (m_oPaintRect.bottom - m_oPaintRect.top) / 2 - x * (m_oPaintRect.bottom - m_oPaintRect.top) / 65536;

int CLaWaveCapture::AnalyzeData()
{
	DWORD nStatus = 0;

	if (!m_pDsCapBuff)
		return -1;

	m_pDsCapBuff->GetStatus(&nStatus);
	if (!((DSCBSTATUS_CAPTURING & nStatus) && (DSCBSTATUS_LOOPING & nStatus)))
		return -1;

	DWORD nReadPosEnd;
	DWORD nCapturePos;
	int nFrameBytes = m_nAnalyzeSamples * sizeof(short int);
	if (FAILED(m_pDsCapBuff->GetCurrentPosition(&nCapturePos, &nReadPosEnd)))
		return -1;

	// get read start pos
	//int nReadPosStart = m_nNextPeriodStartPos;
	if (0 > m_nNextPeriodStartPos)
	{
		// always read 1 frame data at first time since buffer be init
		m_nNextPeriodStartPos = nReadPosEnd - nFrameBytes * 2;
		if (0 > m_nNextPeriodStartPos)
			m_nNextPeriodStartPos += m_oCaptureBufferDesc.dwBufferBytes;
	}

	// calc bytes should be read
	int nReadBytes = nReadPosEnd - m_nNextPeriodStartPos;
	if (nReadBytes < 0)
		nReadBytes += m_oCaptureBufferDesc.dwBufferBytes;

	int nReadTimes = nReadBytes / (nFrameBytes * 2);
	if (0 == nReadTimes)
		return -1;

	// correct read bytes
	nReadBytes = nReadTimes * nFrameBytes * 2;

	short int *pHeadPortion, *pTailPortion;
	DWORD nHpBytes, nTpBytes;
	if (FAILED(m_pDsCapBuff->Lock(m_nNextPeriodStartPos, nReadBytes, (LPVOID *)&pHeadPortion, &nHpBytes, (LPVOID *)&pTailPortion, &nTpBytes, 0)))
		return -1;

	DWORD i, nBase = 0;
	BOOL bTestFlg = FALSE; //(0 == (++m_nTestInt / 10) % 2);
	int s = 0;
	for (int nFrame = 0; nFrame < nReadTimes; ++nFrame)
	{
		for (i = 0; i < nFrameBytes && (nBase + i) < nHpBytes / sizeof(short int); ++i)
		{
			m_pWavBuff[i] = pHeadPortion[nBase + i];
			s += abs(m_pWavBuff[i]);

			if (bTestFlg)
			{
				if (++m_nTestIndex == m_nTestBuffLen)
					m_nTestIndex = 0;

				int t = (int)m_pWavBuff[i] + (int)m_pTestBuff[m_nTestIndex];
				m_pWavBuff[i] = min(32767, t);
				m_pWavBuff[i] = max(-32767, t);
			}
		}

		// nFrameBytes same as (nFrameBytes * 2 / sizeof(short int))
		for (; i < nFrameBytes; ++i)
		{
			m_pWavBuff[i] = pTailPortion[nBase + i];
			s += abs(m_pWavBuff[i]);

			if (bTestFlg)
			{
				if (++m_nTestIndex == m_nTestBuffLen)
					m_nTestIndex = 0;

				int t = (int)m_pWavBuff[i] + (int)m_pTestBuff[m_nTestIndex];
				m_pWavBuff[i] = min(32767, t);
				m_pWavBuff[i] = max(-32767, t);
			}
		}

		//static int dddd = 100;
		//_ASSERT(dddd != 0 || 0 != s);
		//if (0 < dddd)
		//	--dddd;

		m_nCwState = FALSE;
		m_pFft->Encode(m_pDctBuff, m_pWavBuff);
		//m_pFft->Decode(m_pWavBuff, m_pDctBuff);
		if (NULL != m_pCwEventListener)
			m_pCwEventListener->OnCwEvent(m_nCwState);

		m_nCwState = FALSE;
		m_pFft->Encode(m_pDctBuff, m_pWavBuff + m_nAnalyzeSamples);
		//m_pFft->Decode(m_pWavBuff + m_nAnalyzeSamples, m_pDctBuff);
		if (NULL != m_pCwEventListener)
			m_pCwEventListener->OnCwEvent(m_nCwState);

		nBase += nFrameBytes;
	}

	m_pDsCapBuff->Unlock(pHeadPortion, nHpBytes, pTailPortion, nTpBytes);

	if ((m_nNextPeriodStartPos += nReadBytes) >= m_oCaptureBufferDesc.dwBufferBytes)
		m_nNextPeriodStartPos -= m_oCaptureBufferDesc.dwBufferBytes;

	return GetSyncPos(m_pWavBuff, m_nAnalyzeSamples);
}

short int CLaWaveCapture::OnEncodeFilter(float val, int i)
{
	if (!m_nCwState && m_nRecvThreshold <= abs(val))
	{
		int nFreq = i * m_oFormat.nSamplesPerSec / 2 / m_nAnalyzeSamples;
		if (m_nRecvFreqStart <= nFreq && nFreq <= m_nRecvFreqEnd)
			m_nCwState = TRUE;
	}

	if (m_pNextFilter)
		return m_pNextFilter->OnEncodeFilter(val, i);

	return val;
}

short int CLaWaveCapture::OnDecodeFilter(float val, int i)
{
	return val;
}

/***
 * ˢ¿ؼػߣȡƵݣ
 *
 */
BOOL CLaWaveCapture::Refresh()
{
	if (m_bRulerInvalid)
		DrawRuler();

	int nSyncStart = AnalyzeData();

	if (0 > nSyncStart)
		return FALSE;

	if (m_bFraze)
		return TRUE;
	// redraw data if need

	m_pPaintBoard->SetColor(m_nBgColor);
	//m_oPaintRect.left += 1;
	m_pPaintBoard->DrawRect(&m_oPaintRect);
	//m_oPaintRect.left -= 1;

	DrawGrid();

	m_pPaintBoard->SetColor(m_nWaveColor);
	short int* pSyncWavBuff = m_pWavBuff + nSyncStart;

	int last, curr;
	TRANSFORM_SAMPLE(pSyncWavBuff[0], last);

	int i, x1, x2 = m_nBorderWidth;
	for (i = 1; m_nWaveState && i < m_nAnalyzeSamples; ++i)
	{
		int v = pSyncWavBuff[i];
		TRANSFORM_SAMPLE(v, curr);
		x1 = x2;
		x2 = m_nBorderWidth + m_nRulerWidthH * i / m_nAnalyzeSamples;
		m_pPaintBoard->DrawLine(x1, last, x2, curr);
		last = curr;
	}

	m_pPaintBoard->SetColor(m_nFreqAnaColor);

	//FFT
	//m_pFft->Compute(m_pDctBuff, pSyncWavBuff);

	//m_pPaintBoard->SetColor(RGB(0, 0, 0));
	int fd, v, l = 1;
	float db;
//	BOOL bState = FALSE;
	for (i = 0; i < m_nAnalyzeSamples; i += 2)
	{
		short int nFreq = (short int)(i * m_oFormat.nSamplesPerSec / 2 / m_nAnalyzeSamples);
		for (; m_nDctState && l < m_nRulerWidthH; ++l)
		{
			if (m_pFreqRuler[l] >= nFreq)
			{
				v = 0;
				switch (m_nDctState)
				{
					case DCT_LINEAR:
					case DCT_LINEAR_FLOAT:
						v = abs(m_pDctBuff[i]) * m_oPaintRect.bottom / 32768;
						break;
					case DCT_LOG10:
					case DCT_LOG10_FLOAT:
						db = log10f((float)abs(m_pDctBuff[i]));
						if (db > LOG_SAMPLE_RANGE - 4)
							v = (int)((log10f((float)(abs(m_pDctBuff[i]))) - (LOG_SAMPLE_RANGE - 4)) * m_oPaintRect.bottom / 4);
						break;
				}

				if (v > m_oPaintRect.bottom)
					v = m_oPaintRect.bottom;
				m_pPaintBoard->DrawLine(l, m_oPaintRect.bottom - v, l, m_oPaintRect.bottom);

				switch (m_nDctState)
				{
				case DCT_LINEAR_FLOAT:
				case DCT_LOG10_FLOAT:
					fd = (int)(0.005f * m_pFloatClear[i] * m_pFloatClear[i] * m_pFloatClear[i]);

					if (m_pFloatLine[i] - fd < v)
					{
						m_pFloatLine[i] = v;
						m_pFloatClear[i] = 0;
					}
					else if (1 < m_pFloatLine[i] - fd)
					{
						m_pPaintBoard->SetColor(m_nFloatColor);
						fd = m_oPaintRect.bottom - (m_pFloatLine[i] - fd);
						m_pPaintBoard->DrawLine(l, fd, l, fd + 2);
						++m_pFloatClear[i];
						m_pPaintBoard->SetColor(m_nFreqAnaColor);
					}
				}

				break;
			}
		}

//		if (!bState && m_nRecvThreshold <= abs(m_pDctBuff[i]))
//			if (m_nRecvFreqStart <= nFreq && nFreq <= m_nRecvFreqEnd)
//				bState = TRUE;
	} // end of for (i = 0; i < m_nAnalyzeSamples; ++i)

	RECT r = m_oPaintRect;
	r.left += 2;
	r.top += 2;
	r.right = r.left + 32;
	r.bottom = r.top + 12;
	
	switch(m_nWaveState)
	{
	case WAVE_INVISIBLE:
		m_pPaintBoard->SetColor(m_nDisabledColor);
		m_pPaintBoard->DrawText(&r, "W", DT_LEFT); break;
	case WAVE_ORIGINAL:
		m_pPaintBoard->SetColor(m_nEnabledColor);
		m_pPaintBoard->DrawText(&r, "W", DT_LEFT); break;
	default:
		char szBuff[16];
		m_pPaintBoard->SetColor(m_nEnabledColor);
		sprintf(szBuff, "W +%ddB", 6 * (m_nWaveState - WAVE_ORIGINAL));
		m_pPaintBoard->DrawText(&r, szBuff, DT_LEFT); break;
	}

	OffsetRect(&r, 100, 0);

	switch(m_nDctState)
	{
	case DCT_INVISIBLE:
	case DCT_LOG10:
	case DCT_LINEAR:
		m_pPaintBoard->SetColor(m_nDisabledColor);
		m_pPaintBoard->DrawText(&r, "~~~", DT_LEFT); break;
	case DCT_LOG10_FLOAT:
	case DCT_LINEAR_FLOAT:
		m_pPaintBoard->SetColor(m_nEnabledColor);
		m_pPaintBoard->DrawText(&r, "~~~", DT_LEFT); break;
	}

	OffsetRect(&r, 32, 0);

	switch(m_nDctState)
	{
	case DCT_INVISIBLE:
		m_pPaintBoard->SetColor(m_nDisabledColor);
		m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
		OffsetRect(&r, 32, 0);
		m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
	case DCT_LOG10_FLOAT:
	case DCT_LOG10:
		m_pPaintBoard->SetColor(m_nEnabledColor);
		m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
		OffsetRect(&r, 32, 0);
		m_pPaintBoard->SetColor(m_nDisabledColor);
		m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
	case DCT_LINEAR_FLOAT:
	case DCT_LINEAR:
		m_pPaintBoard->SetColor(m_nDisabledColor);
		m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
		OffsetRect(&r, 32, 0);
		m_pPaintBoard->SetColor(m_nEnabledColor);
		m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
	}

	//r = m_oPaintRect;
	//OffsetRect(&r, m_oRect.left, m_oRect.top);
	//m_pParent->Invalidate(&r);
	m_pParent->Invalidate(&m_oRect);

//	if (NULL != m_pCwEventListener)
//		m_pCwEventListener->OnCwEvent(bState);

	return TRUE;
}

DWORD CLaWaveCapture::GetSyncPos(short int* pBuff, DWORD nBuffSize)
{
	//synchronize the wave
	int nStep = 1;
	DWORD nSyncStart;
	for (nSyncStart = 0; nSyncStart < nBuffSize - 1 && 0 < nStep; ++nSyncStart)
	{
		switch(nStep)
		{
			case 1:
				if (pBuff[nSyncStart] < pBuff[nSyncStart + 1])
					nStep = 2;
				break;
			case 2:
				if (pBuff[nSyncStart] >= 0 && pBuff[nSyncStart] > pBuff[nSyncStart + 1])
					nStep = 0;
			/* for sin wave
			case 1: // look for negative
				if (m_vWavBuff[nSyncStart] < 0)
					nStep = 2;
				break;
			case 2: // through the X axis
				if (m_vWavBuff[nSyncStart] >= 0)
					nStep = 0;
				break;
			*/
		}
	}

	return nSyncStart;
}

BOOL CLaWaveCapture::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
	return FALSE;
}

BOOL CLaWaveCapture::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
	switch(nMkt)
	{
		case LBUTTON:
		{
			if (WAVE_GAIN_X32 < ++m_nWaveState)
				m_nWaveState = 0;

			m_nWaveStateTip = 50;
			return TRUE;
		}
		case RBUTTON:
		{
			if (DCT_LINEAR < ++m_nDctState)
				m_nDctState = 0;

			m_nDctStateTip = 50;
			m_bRulerInvalid = TRUE;
			return TRUE;
		}
	}

	return FALSE;
}

void CLaWaveCapture::SetBackgroundColor(int nColor)
{
	m_nBgColor = nColor;
}

void CLaWaveCapture::SetWaveColor(int nColor)
{
	m_nWaveColor = nColor;
}

void CLaWaveCapture::SetFloatColor(int nColor)
{
	m_nFloatColor = nColor;
}

void CLaWaveCapture::SetFreqAnaColor(int nColor)
{
	m_nFreqAnaColor = nColor;
}

void CLaWaveCapture::InitTestBuffer()
{
	REAL f = 1000.0f;
	REAL w = 1.0f / f;
	REAL d = 1.0f / 44100.0f;
	int nTimes;
	for (nTimes = 100; nTimes <= 1000; ++nTimes)
	{
		REAL rRemScale = fmod(w * nTimes, d) / w;

		if (rRemScale < 0.001l || rRemScale > 0.998l)
			break;
	}

	REAL s = nTimes * w;
	m_nTestBuffLen = s * 44100;
	REAL DW = 2 * PI / m_oFormat.nSamplesPerSec;
	m_pTestBuff = new short int[m_nTestBuffLen];

	for (DWORD i = 0; i < m_nTestBuffLen; ++i)
	{
		REAL v = sin(DW * i * f * 3) * 0.3 + sin(DW * i * f * 2) * 0.4 + sin(DW * i * f) * 0.5;	// -1.0 ~ +1.0
		m_pTestBuff[i] = (short int)(v * 32767);
	}
}

================================================
FILE: src/LaWaveCapture.h
================================================
#pragma once

#include "EventManagerWin32.h"
#include "FFT.h"
#include "dsound.h"

//log(32768)
//#define LOG_SAMPLE_RANGE	4.51545	
#define LOG_SAMPLE_RANGE	4.51545f

// CLaWaveCapture.m_nWaveState values
#define WAVE_INVISIBLE		0
#define WAVE_ORIGINAL		1
#define WAVE_GAIN_X2		2
#define WAVE_GAIN_X4		3
#define WAVE_GAIN_X8		4
#define WAVE_GAIN_X16		5
#define WAVE_GAIN_X32		6

// CLaWaveCapture.m_nDctState values
#define DCT_INVISIBLE		0
#define DCT_LOG10_FLOAT		1
#define DCT_LOG10			2
#define DCT_LINEAR_FLOAT	3
#define DCT_LINEAR			4

class ICwEventListener
{
public:
	virtual void OnCwEvent(BOOL bCwDown) = 0;
};

class CLaWaveCapture
	: public IPaintEventControl
	, public IMouseKeyEventControl
	, public IFilterDFT<short int, float>
{
public:
	CLaWaveCapture(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSample, IFilterDFT<short int, float>* pNextFilter, ICwEventListener* pCwEventListener = NULL);
	~CLaWaveCapture(void);

	virtual BOOL IsRelated(int x, int y);
	virtual void GetRect(RECT* r);
	virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);

	virtual BOOL Initialize();
	virtual BOOL Refresh();

	virtual void SetThresholdLevel(double rThresholdLevel);
	virtual void SetFreqRange(int nLowFreq, int nHighFreq);

	virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
	virtual BOOL OnClick(void* owner) { return FALSE; };

	virtual short int OnEncodeFilter(float val, int i);
	virtual short int OnDecodeFilter(float val, int i);

	void SetBackgroundColor(int nColor);
	void SetWaveColor(int nColor);
	void SetFloatColor(int nColor);
	void SetFreqAnaColor(int nColor);

	BOOL GetFrazeState() { return m_bFraze; };
	void SetFrazeState(BOOL bFraze) { m_bFraze = bFraze; }

private:
	int AnalyzeData();
	DWORD GetSyncPos(short int* pBuff, DWORD nBuffSize);

	void DrawRuler();
	void DrawBorder();
	void DrawGrid();

	IPaintableParent*		m_pParent;
	CFont*		m_pFont;
	RECT		m_oRect;	// by parent
	RECT		m_oPaintRect;	// by self
	RECT		m_oRulerRectH;	// by self
	RECT		m_oRulerRectV;	// by self
	int		m_nRulerWidthH;
	int		m_nRulerWidthV;
	int		m_nRulerGridsV;
	int		m_nRulerDbMax;
	CGraphics*	m_pPaintBoard;

	IDirectSoundCapture*		m_pDsCap;
	IDirectSoundCaptureBuffer*	m_pDsCapBuff;

	WAVEFORMATEX		m_oFormat;
	DSCBUFFERDESC		m_oCaptureBufferDesc;
	int		m_nNextPeriodStartPos;

	short int*	m_pWavBuff; //[m_nAnalyzeSamples * 2];
	short int*	m_pDctBuff; //[m_nAnalyzeSamples];
	short int*	m_pFreqRuler; //[m_oRulerWidth];
	short int*	m_pFloatLine; //[m_nAnalyzeSamples];
	short int*  m_pFloatClear;

//	TCosDFT<short int, float>*		m_pFft;
	TFastFT<short int, float>*		m_pFft;
	IFilterDFT<short int, float>*	m_pNextFilter;

	ICwEventListener* m_pCwEventListener;
	DWORD		m_nAnalyzeSamples;
	int			m_nRecvThreshold;
	int			m_nRecvFreqStart;
	int			m_nRecvFreqEnd;

	BOOL		m_nCwState;

	short int	m_nWaveState;
	short int	m_nDctState;
	int			m_nWaveStateTip;
	int			m_nDctStateTip;

	int			m_nBorderWidth;
	int			m_nRularH;
	int			m_nRularV;

	int			m_nBgColor;
	int			m_nWaveColor;
	int			m_nFloatColor;
	int			m_nFreqAnaColor;
	int			m_nRulerColorH;
	int			m_nRulerColorV;
	int			m_nGridColorH;
	int			m_nGridColorV;
	int			m_nEnabledColor;
	int			m_nDisabledColor;

	BOOL		m_bRulerInvalid;
	BOOL		m_bFraze;


	/* for test only */
	int			m_nTestBuffLen;
	int			m_nTestIndex;
	short int*	m_pTestBuff;
	void		InitTestBuffer();
	int			m_nTestInt;
};


================================================
FILE: src/LaWaveFile.cpp
================================================
#include "StdAfx.h"
#include "stdio.h"
#include "math.h"
#include "assert.h"
#include "LaWaveFile.h"

#define RESOLVEDWORD(a, b, c, d) (((DWORD)(a)) | (((DWORD)(b)) << 8) | (((DWORD)(c)) << 16) | (((DWORD)(d)) << 24))
#define PI				3.1415926f

CWaveFile::CWaveFile(const char* pPathname, WORD nChannels, DWORD nSamplesPerSec, WORD  wBitsPerSample, float rSampleBuffSec)
{
	m_pDestFile = fopen(pPathname, "wb");
	memset(&m_oWaveFileInfo, 0, sizeof(m_oWaveFileInfo));
	m_oWaveFileInfo.nRiffFlag = RESOLVEDWORD('R', 'I', 'F', 'F');
	m_oWaveFileInfo.nCbSize = 
		sizeof(m_oWaveFileInfo) - sizeof(m_oWaveFileInfo.nRiffFlag) - sizeof(m_oWaveFileInfo.nCbSize);
	m_oWaveFileInfo.oWaveHeader.nWaveFlag = RESOLVEDWORD('W', 'A', 'V', 'E');
	m_oWaveFileInfo.oWaveHeader.nFmtFlag = RESOLVEDWORD('f', 'm', 't', ' ');
	m_oWaveFileInfo.oWaveHeader.nCbSize = sizeof(m_oWaveFileInfo.oWaveHeader.oWaveInfo);
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.nBlank = 1;
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels = nChannels;
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.nSamplesPerSec = nSamplesPerSec;
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec = 
		nSamplesPerSec * nChannels * wBitsPerSample / 8;
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.nBlockAlign = nChannels * wBitsPerSample / 8;
	m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample = wBitsPerSample;
	m_oWaveFileInfo.oWaveHeader.nDataFlag = RESOLVEDWORD('d', 'a', 't', 'a');
	m_oWaveFileInfo.oWaveHeader.nDataLength = 0;

	fwrite(&m_oWaveFileInfo, sizeof(m_oWaveFileInfo), 1, m_pDestFile);

	m_rSampleBuffSec = rSampleBuffSec;

	m_nWavBuffLen = (int)(rSampleBuffSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
	m_pWavBuff = new char[m_nWavBuffLen];
	m_bModified = TRUE;
}

CWaveFile::~CWaveFile()
{
	delete[] m_pWavBuff;
	fclose(m_pDestFile);
}

void CWaveFile::SetFreq(float rFreq)
{
	m_rFreq = rFreq;
	m_bModified = TRUE;
}

void CWaveFile::SetVolumn(float rVol)
{
	m_rVol = rVol;
	m_bModified = TRUE;
}

int CWaveFile::AppendRaw(const char* pBuff, DWORD nLen, int nCount)
{
	assert(0 == (nLen * nCount) % 2);
	DWORD nBlockSize = nLen * nCount;

	m_oWaveFileInfo.nCbSize += nBlockSize;
	m_oWaveFileInfo.oWaveHeader.nDataLength += nBlockSize;

	fseek(m_pDestFile, 0, SEEK_END);
	for (int i = 0; i < nCount; ++i)
		fwrite(pBuff, 1, nLen, m_pDestFile);

	fseek(m_pDestFile, 0, SEEK_SET);
	fwrite(&m_oWaveFileInfo, sizeof(m_oWaveFileInfo), 1, m_pDestFile);
	return nBlockSize;
}

int CWaveFile::AppendBlank(float rSec)
{
	DWORD nBytes = (DWORD)(rSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
	if (0 != nBytes % 2)
		++nBytes;
	char c = '\0';
	return AppendRaw(&c, 1, nBytes);
}

int CWaveFile::Append(float rSec)
{
	if (m_bModified)
	{
		InitWavBuff();
	}
	
	DWORD nBytes = (DWORD)(rSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
	if (0 != nBytes % 2)
		++nBytes;

	assert(nBytes <= m_nWavBuffLen);
	return AppendRaw(m_pWavBuff, nBytes, 1);
}

void CWaveFile::InitWavBuff()
{
	float dt = 1.0f / m_oWaveFileInfo.oWaveHeader.oWaveInfo.nSamplesPerSec;
	DWORD nBytesPerSample = m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample / 8;

	for (DWORD i = 0; i < m_nWavBuffLen / nBytesPerSample; ++i)
	{
		float v = sin(2 * PI * dt * i * m_rFreq) * m_rVol;	// -1.0 ~ +1.0

		for (DWORD j = 0; j < m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels; ++j)
		{
			if (16 == m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample)
			{
				*(((short int *)m_pWavBuff) + i * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels + j) = (short int)(v * 32767);
			}
			else if (8 == m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample)
			{
				*(((char *)m_pWavBuff) + i * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels + j) = (char)(v * 255);
			}
			else
			{
				assert(0);
			}
		}
	}

	m_bModified = FALSE;
}



================================================
FILE: src/LaWaveFile.h
================================================

typedef struct
{
	DWORD	nRiffFlag;		//'RIFF'
	DWORD	nCbSize;
	struct
	{
		DWORD nWaveFlag;	//'WAVE'
		DWORD nFmtFlag;		//'fmt '
		DWORD nCbSize;
		struct
		{
			WORD nBlank;
			WORD nChannels;
			DWORD nSamplesPerSec; 
			DWORD nAvgBytesPerSec; 
			WORD  nBlockAlign; 
			WORD  wBitsPerSample;
		} oWaveInfo;
		DWORD nDataFlag;	//'data'
		DWORD nDataLength;
	} oWaveHeader;
} LAAUDIOFILEHEADER;

class CWaveFile
{
public:
	CWaveFile(const char* pPathname, WORD nChannels, DWORD nSamplesPerSec, WORD  wBitsPerSample, float rSampleBuffSec);
	~CWaveFile();
	int AppendRaw(const char* pBuff, DWORD nLen, int nCount);
	void SetFreq(float rFreq);
	void SetVolumn(float rVol);
	int Append(float rSec);
	int AppendBlank(float rSec);

private:
	void InitWavBuff();
	FILE* m_pDestFile;
	LAAUDIOFILEHEADER m_oWaveFileInfo;
	char*	m_pWavBuff;
	DWORD	m_nWavBuffLen;
	BOOL	m_bModified;

	float	m_rSampleBuffSec;
	float	m_rFreq;
	float	m_rVol;
};


================================================
FILE: src/Lakey.h
================================================
#pragma once

#include "resource.h"


================================================
FILE: src/Lakey.rc
================================================
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// (壬й) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_LAKEY               ICON                    "Lakey.ico"

IDI_SMALL               ICON                    "small.ico"


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDC_LAKEY MENU
BEGIN
    POPUP "ļ(&F)"
    BEGIN
        MENUITEM "˳(&X)",                      IDM_EXIT
    END
    POPUP "(&T)"
    BEGIN
        MENUITEM "CWƵļ(&W)",                IDM_PROMPTWAVE
        MENUITEM SEPARATOR
        MENUITEM "Kochѵ\tCtrl+K",             IDM_KOCHSTART
        MENUITEM "KochƵļ(&G)",              IDM_KOCHWAVE
        MENUITEM SEPARATOR
        MENUITEM "ѵ(&T)",                    IDM_SENDTRAINING
        MENUITEM SEPARATOR
        MENUITEM "(&S)",                      IDM_SETTINGS
    END
    POPUP "(&H)"
    BEGIN
        MENUITEM "(&A)...",                   IDM_ABOUT
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

IDC_LAKEY ACCELERATORS
BEGIN
    "/",            IDM_ABOUT,              ASCII,  ALT, NOINVERT
    "?",            IDM_ABOUT,              ASCII,  ALT, NOINVERT
    "K",            IDM_KOCHSTART,          VIRTKEY, CONTROL, NOINVERT
    VK_ESCAPE,      IDM_KOCHSTOP,           VIRTKEY, NOINVERT
END


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_ABOUTBOX DIALOGEX 22, 17, 215, 73
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Lakey"
FONT 9, "Arial", 400, 0, 0x0
BEGIN
    CONTROL         IDB_BITMAP1,IDC_MYICON,"Static",SS_BITMAP | SS_REALSIZEIMAGE | WS_BORDER,5,7,62,51
    LTEXT           "Lakey Version 2.2.0020 (Paper)",IDC_STATIC,76,6,129,8,SS_NOPREFIX
    LTEXT           "(C) 2006-2020",IDC_STATIC,76,16,129,8
    LTEXT           "DE BG1VLZ, idirect3d@hotmail.com, VY",IDC_STATIC,76,38,132,8
    LTEXT           "-.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.-",IDC_STATIC,6,63,203,8
    LTEXT           "73 ^_^",IDC_STATIC,76,49,132,8
END

IDD_PROMPTBOX DIALOGEX 22, 17, 215, 73
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION ""
FONT 9, "Arial", 400, 0, 0x0
BEGIN
    LTEXT           ": ",IDC_PROMPTTEXT,7,10,200,8
    EDITTEXT        IDC_INPUTSTR,7,33,200,12,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
    PUSHBUTTON      "ύ",IDOK,155,56,47,10
    PUSHBUTTON      "ȡ",IDCANCEL,100,56,47,10
END

IDD_SETTINGS DIALOGEX 22, 17, 254, 194
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Settings"
FONT 9, "MS Shell Dlg", 400, 0, 0x0
BEGIN
    CONTROL         "",IDC_SETTINGSTAB,"SysTabControl32",0x0,2,3,249,170
    PUSHBUTTON      "ȷ",IDC_ACCEPT,190,178,47,12
    PUSHBUTTON      "ȡ",IDCANCEL,135,178,47,12
END

IDD_COPYPAD DIALOGEX 0, 0, 343, 199
STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW
CAPTION ""
FONT 8, "Courier New", 400, 0, 0x0
BEGIN
    CONTROL         "",IDC_COPYTEXT,"RichEdit20A",ES_MULTILINE | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,342,175
    DEFPUSHBUTTON   "",IDC_ACCEPT,277,181,55,12
    LTEXT           "00:00:00",IDC_ELAPSETIME,9,184,37,10
    RTEXT           "0",IDC_COPIED,59,184,37,10
    RTEXT           "0",IDC_INCORRECT,109,184,37,10
    RTEXT           "0%",IDC_CORRECTPERC,159,184,37,10
    GROUPBOX        "ʱ",IDC_STATIC,3,176,47,21
    GROUPBOX        "¼",IDC_STATIC,53,176,47,21
    GROUPBOX        "",IDC_STATIC,103,176,47,21
    GROUPBOX        "ȷ",IDC_STATIC,153,176,47,21
END

IDD_TEST DIALOGEX 0, 0, 348, 148
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "ȷ",IDOK,291,7,50,14
    PUSHBUTTON      "ȡ",IDCANCEL,291,24,50,14
    CONTROL         "",IDC_RICHEDIT21,"RichEdit20A",ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP,7,7,180,134
END

IDD_GENERAL DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    EDITTEXT        IDC_SHORTHIT,42,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_HITDELAY,137,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_SPEED,218,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_LONGHIT,42,32,29,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_LETTERDELAY,137,32,29,14,ES_AUTOHSCROLL | ES_NUMBER
    PUSHBUTTON      "",IDC_CALCSPEED,199,33,77,12
    GROUPBOX        "CW",IDC_STATIC,4,2,276,52
    LTEXT           """""",IDC_STATIC,8,17,35,9
    LTEXT           "(ms)",IDC_STATIC,76,17,19,9
    LTEXT           """""",IDC_STATIC,8,35,35,9
    LTEXT           "(ms)",IDC_STATIC,76,35,19,9
    LTEXT           "",IDC_STATIC,103,17,35,9
    LTEXT           "(ms)",IDC_STATIC,171,35,19,9
    LTEXT           "ַ",IDC_STATIC,103,35,35,9
    LTEXT           "(ms)",IDC_STATIC,171,17,19,9
    LTEXT           "",IDC_STATIC,199,17,18,9
    LTEXT           "(wpm)",IDC_STATIC,252,17,23,9
    LTEXT           "ͨڡ١¼Ҫļ٣WPMֵɣԶ㡣΢˳١IJͨ١ť㵱ǰֵ",IDC_STATIC,19,70,244,33
END

IDD_SEND DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    EDITTEXT        IDC_BEEPFREQ,49,14,53,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_BEEPVOL,49,32,53,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_SENDPERIOD,49,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_SENDILDELIMIT,184,14,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_CW,184,32,53,14,ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER
    EDITTEXT        IDC_WORDDELAY,184,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "趨ǺͷصIJ",IDC_STATIC,26,78,237,33
    GROUPBOX        "",IDC_STATIC,4,2,276,68
    LTEXT           "",IDC_STATIC,10,17,20,9
    LTEXT           "(Hz)",IDC_STATIC,107,17,17,9
    LTEXT           "",IDC_STATIC,10,35,20,9
    LTEXT           "0~1.0",IDC_STATIC,106,35,22,9
    LTEXT           "",IDC_STATIC,9,53,35,9
    LTEXT           "(ms)",IDC_STATIC,107,53,19,9
    LTEXT           "ֹͣ",IDC_STATIC,144,16,35,9
    LTEXT           "(ms)",IDC_STATIC,242,16,19,9
    LTEXT           "CW",IDC_STATIC,144,35,35,9
    LTEXT           "VK code",IDC_STATIC,242,35,31,9
    LTEXT           "ոӳ",IDC_STATIC,144,53,35,9
    LTEXT           "(ms)",IDC_STATIC,242,53,19,9
END

IDD_RECV DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    EDITTEXT        IDC_RECVANALYZESAMPLES,49,14,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_RECVPERIOD,49,32,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_RECVILDELIMIT,49,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_RECVTHRESHOLD,184,14,53,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_RECVFREQSTART,184,32,53,14,ES_AUTOHSCROLL | ES_NUMBER
    EDITTEXT        IDC_RECVFREQEND,184,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "趨ǺձصIJ",IDC_STATIC,26,78,237,33
    GROUPBOX        "",IDC_STATIC,4,2,276,69
    LTEXT           "",IDC_STATIC,9,17,35,9
    LTEXT           "()",IDC_STATIC,107,17,14,9
    LTEXT           "",IDC_STATIC,9,35,35,9
    LTEXT           "(ms)",IDC_STATIC,107,35,19,9
    LTEXT           "ֹͣ",IDC_STATIC,9,53,35,9
    LTEXT           "(ms)",IDC_STATIC,107,53,19,9
    LTEXT           "ֵƽ",IDC_STATIC,144,17,35,9
    LTEXT           "0~1.0",IDC_STATIC,242,17,22,9
    LTEXT           "ʼƵ",IDC_STATIC,144,35,35,9
    LTEXT           "(Hz)",IDC_STATIC,242,35,17,9
    LTEXT           "ֹƵ",IDC_STATIC,144,53,35,9
    LTEXT           "(Hz)",IDC_STATIC,242,53,17,9
END

IDD_IO DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    CONTROL         "",IDC_EXTPORTENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,16,37,9
    EDITTEXT        IDC_EXTPORTADDR,99,14,37,14,ES_UPPERCASE | ES_READONLY
    EDITTEXT        IDC_OPENBYTE,188,14,15,14,ES_UPPERCASE
    EDITTEXT        IDC_CLOSEBYTE,251,14,15,14,ES_UPPERCASE
    LTEXT           "»̧CWʱLakeyָӲ˿ڵַضݣԱһЩΧ豸",IDC_STATIC,20,44,244,22
    GROUPBOX        "˿ڿ",IDC_STATIC,4,2,276,32
    LTEXT           "ַ(HEX)",IDC_STATIC,59,16,37,9
    LTEXT           "(HEX)",IDC_STATIC,146,16,37,9
    LTEXT           "ر(HEX)",IDC_STATIC,211,16,37,9
    LTEXT           "ע⣺ȷӲַ趨пܻżһЩӲ²ϵͳ쳣޸ģ",IDC_STATIC,19,90,244,25,WS_BORDER
    LTEXT           "(ö˿ڵַοֵ - 278H/378H - 3E8H/3F8H/2F8H)",IDC_STATIC,25,70,237,16
END

IDD_KOCH DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    EDITTEXT        IDC_KOCHCHARS,49,14,223,14,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
    EDITTEXT        IDC_KOCHWORDLEN,49,32,25,14,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "ڡַKOCHѵҪѵĸѵʱѡȡַеַѵÿšֳȡַһո񡱣һȣͣ١",IDC_STATIC,22,67,246,35
    GROUPBOX        "ϰ",IDC_STATIC,4,2,276,55
    LTEXT           "ַ",IDC_STATIC,9,17,31,9
    LTEXT           "ֳ",IDC_STATIC,9,35,32,9
    LTEXT           "Kochַ˳򣩣\n\nK M R S U A P T L O W I . N J E F 0 Y , V G 5 / Q 9 Z H 3 8 B ? 4 2 7 C 1 D 6 X <BT> <SK> <AR>",IDC_STATIC,22,108,245,36
END

IDD_NETWORK DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
EXSTYLE WS_EX_TRANSPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    CONTROL         "",IDC_NWENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,227,15,48,10
    EDITTEXT        IDC_HOSTNAME,51,44,79,14,ES_AUTOHSCROLL
    PUSHBUTTON      "",IDC_HOSTADD,197,44,35,13,BS_FLAT
    PUSHBUTTON      "ɾ",IDC_HOSTDEL,238,44,35,13
    CONTROL         "",IDC_HOSTLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,62,263,62
    EDITTEXT        IDC_LOCALPORT,51,14,30,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
    EDITTEXT        IDC_HOSTPORT,158,44,29,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
    GROUPBOX        "",IDC_STATIC,4,2,276,127
    LTEXT           "ض˿",IDC_STATIC,11,17,32,9
    LTEXT           "ڽڵпӾַ̬㲥ַȡ",IDC_STATIC,17,135,243,13
    LTEXT           "˿",IDC_STATIC,137,47,21,9
    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDHORZ,10,36,265,1
    LTEXT           " - IP",IDC_STATIC,11,47,31,9
END

IDD_SETTINGS2 DIALOGEX 22, 17, 243, 242
STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Settings"
FONT 9, "Arial", 400, 0, 0x0
BEGIN
    GROUPBOX        "",IDC_STATIC,3,3,117,105
    LTEXT           "",IDC_STATIC,7,17,17,8
    EDITTEXT        IDC_BEEPFREQ,41,15,45,12,ES_AUTOHSCROLL
    LTEXT           "(Hz)",IDC_STATIC,90,17,15,8
    LTEXT           "",IDC_STATIC,7,32,17,8
    EDITTEXT        IDC_BEEPVOL,41,30,45,12,ES_AUTOHSCROLL
    LTEXT           "0~1.0",IDC_STATIC,90,32,19,8
    LTEXT           "",IDC_STATIC,7,47,30,8
    EDITTEXT        IDC_SENDPERIOD,41,45,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,91,47,16,8
    LTEXT           "ֹͣ",IDC_STATIC,7,62,30,8
    EDITTEXT        IDC_SENDILDELIMIT,41,60,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,91,62,16,8
    LTEXT           "CW",IDC_STATIC,7,77,30,8
    EDITTEXT        IDC_CW,41,75,45,12,ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER
    LTEXT           "VK code",IDC_STATIC,91,77,27,8
    LTEXT           "ոӳ",IDC_STATIC,7,92,30,8
    EDITTEXT        IDC_WORDDELAY,41,90,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,91,92,16,8
    GROUPBOX        "",IDC_STATIC,125,3,115,105
    LTEXT           "",IDC_STATIC,132,17,30,8
    EDITTEXT        IDC_RECVANALYZESAMPLES,166,15,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "()",IDC_STATIC,216,17,12,8
    LTEXT           "",IDC_STATIC,132,32,30,8
    EDITTEXT        IDC_RECVPERIOD,166,30,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,216,32,16,8
    LTEXT           "ֹͣ",IDC_STATIC,132,47,30,8
    EDITTEXT        IDC_RECVILDELIMIT,166,45,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,216,47,16,8
    LTEXT           "ֵƽ",IDC_STATIC,132,62,30,8
    EDITTEXT        IDC_RECVTHRESHOLD,166,60,45,12,ES_AUTOHSCROLL
    LTEXT           "0~1.0",IDC_STATIC,216,62,19,8
    LTEXT           "ʼƵ",IDC_STATIC,132,77,30,8
    EDITTEXT        IDC_RECVFREQSTART,166,75,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(Hz)",IDC_STATIC,216,77,14,8
    LTEXT           "ֹƵ",IDC_STATIC,132,92,30,8
    EDITTEXT        IDC_RECVFREQEND,166,90,45,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(Hz)",IDC_STATIC,216,92,14,8
    GROUPBOX        "CW",IDC_STATIC,3,110,237,45
    LTEXT           """""",IDC_STATIC,7,122,30,8
    EDITTEXT        IDC_SHORTHIT,36,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,65,122,16,8
    LTEXT           """""",IDC_STATIC,7,136,30,8
    EDITTEXT        IDC_LONGHIT,36,135,25,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,65,136,16,8
    LTEXT           "",IDC_STATIC,88,121,30,8
    EDITTEXT        IDC_HITDELAY,117,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,147,136,16,8
    LTEXT           "ַ",IDC_STATIC,88,136,30,8
    EDITTEXT        IDC_LETTERDELAY,117,135,25,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(ms)",IDC_STATIC,147,121,16,8
    LTEXT           "",IDC_STATIC,170,121,30,8
    EDITTEXT        IDC_SPEED,187,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "(wpm)",IDC_STATIC,216,121,20,8
    PUSHBUTTON      "",IDC_CALCSPEED,170,136,66,10
    GROUPBOX        "˿ڿ",IDC_STATIC,3,156,237,28
    CONTROL         "",IDC_EXTPORTENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,168,32,8
    LTEXT           "ַ(HEX)",IDC_STATIC,51,168,32,8
    EDITTEXT        IDC_EXTPORTADDR,85,166,32,12,ES_UPPERCASE | ES_READONLY
    LTEXT           "(HEX)",IDC_STATIC,125,168,32,8
    EDITTEXT        IDC_OPENBYTE,161,166,13,12,ES_UPPERCASE
    LTEXT           "ر(HEX)",IDC_STATIC,181,168,32,8
    EDITTEXT        IDC_CLOSEBYTE,215,166,13,12,ES_UPPERCASE
    GROUPBOX        "ϰ",IDC_STATIC,3,190,237,28
    LTEXT           "ַ",IDC_STATIC,7,202,32,8
    EDITTEXT        IDC_KOCHCHARS,41,200,138,12,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
    LTEXT           "ֳ",IDC_STATIC,186,202,32,8
    EDITTEXT        IDC_KOCHWORDLEN,215,200,16,12,ES_AUTOHSCROLL | ES_NUMBER
    PUSHBUTTON      "ȷ",IDC_ACCEPT,190,224,47,10
    PUSHBUTTON      "ȡ",IDCANCEL,135,224,47,10
END


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        RIGHTMARGIN, 213
        BOTTOMMARGIN, 72
    END

    IDD_SETTINGS, DIALOG
    BEGIN
        RIGHTMARGIN, 251
    END

    IDD_TEST, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 341
        TOPMARGIN, 7
        BOTTOMMARGIN, 141
    END

    IDD_GENERAL, DIALOG
    BEGIN
        BOTTOMMARGIN, 161
    END

    IDD_SEND, DIALOG
    BEGIN
        RIGHTMARGIN, 280
        BOTTOMMARGIN, 160
    END

    IDD_RECV, DIALOG
    BEGIN
        BOTTOMMARGIN, 122
    END

    IDD_IO, DIALOG
    BEGIN
        BOTTOMMARGIN, 122
    END

    IDD_KOCH, DIALOG
    BEGIN
        BOTTOMMARGIN, 152
    END

    IDD_NETWORK, DIALOG
    BEGIN
        BOTTOMMARGIN, 152
    END
END
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

IDB_LOGO                BITMAP                  "logo.bmp"


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
    IDS_APP_TITLE           "Lakey 2.2 (Paper)"
    IDC_LAKEY               "LAKEY"
END

#endif    // (壬й) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED



================================================
FILE: src/Lakey.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31313.79
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lakey", "Lakey.vcxproj", "{B20DFA3B-4DF4-464C-883D-940012A2178C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test4fft", "..\test4fft\test4fft.vcxproj", "{5A8D8698-A0EF-404A-B421-B49C0336EEB4}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Win32 = Debug|Win32
		Release|Win32 = Release|Win32
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{B20DFA3B-4DF4-464C-883D-940012A2178C}.Debug|Win32.ActiveCfg = Debug|Win32
		{B20DFA3B-4DF4-464C-883D-940012A2178C}.Debug|Win32.Build.0 = Debug|Win32
		{B20DFA3B-4DF4-464C-883D-940012A2178C}.Release|Win32.ActiveCfg = Release|Win32
		{B20DFA3B-4DF4-464C-883D-940012A2178C}.Release|Win32.Build.0 = Release|Win32
		{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Debug|Win32.ActiveCfg = Debug|Win32
		{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Debug|Win32.Build.0 = Debug|Win32
		{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Release|Win32.ActiveCfg = Release|Win32
		{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Release|Win32.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {779ADF4C-AB52-4F67-9F6C-1407590493CD}
	EndGlobalSection
EndGlobal


================================================
FILE: src/Lakey.vcproj
================================================
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="8.00"
	Name="Lakey"
	ProjectGUID="{B20DFA3B-4DF4-464C-883D-940012A2178C}"
	RootNamespace="Lakey"
	Keyword="Win32Proj"
	>
	<Platforms>
		<Platform
			Name="Win32"
		/>
	</Platforms>
	<ToolFiles>
	</ToolFiles>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory="Debug"
			IntermediateDirectory="Debug"
			ConfigurationType="1"
			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
			CharacterSet="2"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories=""
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800"
				MinimalRebuild="true"
				BasicRuntimeChecks="3"
				RuntimeLibrary="1"
				UsePrecompiledHeader="2"
				WarningLevel="3"
				Detect64BitPortabilityProblems="true"
				DebugInformationFormat="4"
				CallingConvention="0"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="dxguid.lib dsound.lib WS2_32.lib Comdlg32.lib User32.lib Gdi32.lib"
				OutputFile="$(OutDir)/Lakey.exe"
				LinkIncremental="2"
				AdditionalLibraryDirectories=""
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(OutDir)/Lakey.pdb"
				SubSystem="2"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCWebDeploymentTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
			/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory="Release"
			IntermediateDirectory="Release"
			ConfigurationType="1"
			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
			CharacterSet="2"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="2"
				InlineFunctionExpansion="1"
				OmitFramePointers="true"
				PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800"
				StringPooling="true"
				RuntimeLibrary="0"
				EnableFunctionLevelLinking="true"
				UsePrecompiledHeader="2"
				WarningLevel="3"
				Detect64BitPortabilityProblems="true"
				DebugInformationFormat="3"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="dxguid.lib dsound.lib WS2_32.lib Comdlg32.lib User32.lib Gdi32.lib"
				OutputFile="$(OutDir)/Lakey.exe"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCWebDeploymentTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
			/>
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Դļ"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			>
			<File
				RelativePath=".\CommFunc.cpp"
				>
			</File>
			<File
				RelativePath="EventListener.cpp"
				>
			</File>
			<File
				RelativePath="EventManagerWin32.cpp"
				>
			</File>
			<File
				RelativePath="FFT.cpp"
				>
			</File>
			<File
				RelativePath="Graphics.cpp"
				>
			</File>
			<File
				RelativePath="LaButton.cpp"
				>
			</File>
			<File
				RelativePath=".\LaHwControl.cpp"
				>
			</File>
			<File
				RelativePath="LaJournalPanel.cpp"
				>
			</File>
			<File
				RelativePath=".\LakeyMain.cpp"
				>
			</File>
			<File
				RelativePath="LakeyMainWindow.cpp"
				>
			</File>
			<File
				RelativePath="LakeySetting.cpp"
				>
			</File>
			<File
				RelativePath="LaLabel.cpp"
				>
			</File>
			<File
				RelativePath="LaLine.cpp"
				>
			</File>
			<File
				RelativePath=".\LaNetwork.cpp"
				>
			</File>
			<File
				RelativePath="LaTuner.cpp"
				>
			</File>
			<File
				RelativePath="LaWaveCapture.cpp"
				>
			</File>
			<File
				RelativePath=".\LaWaveFile.cpp"
				>
			</File>
			<File
				RelativePath="MorseParser.cpp"
				>
			</File>
			<File
				RelativePath=".\mytest.cpp"
				>
			</File>
			<File
				RelativePath="SinSound.cpp"
				>
			</File>
			<File
				RelativePath="stdafx.cpp"
				>
				<FileConfiguration
					Name="Debug|Win32"
					>
					<Tool
						Name="VCCLCompilerTool"
						UsePrecompiledHeader="1"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					>
					<Tool
						Name="VCCLCompilerTool"
						UsePrecompiledHeader="1"
					/>
				</FileConfiguration>
			</File>
		</Filter>
		<Filter
			Name="ͷļ"
			Filter="h;hpp;hxx;hm;inl;inc"
			>
			<File
				RelativePath=".\CommFunc.h"
				>
			</File>
			<File
				RelativePath="EventListener.h"
				>
			</File>
			<File
				RelativePath="EventManagerWin32.h"
				>
			</File>
			<File
				RelativePath="FFT.h"
				>
			</File>
			<File
				RelativePath="Graphics.h"
				>
			</File>
			<File
				RelativePath="LaButton.h"
				>
			</File>
			<File
				RelativePath=".\LaHwControl.h"
				>
			</File>
			<File
				RelativePath="LaJournalPanel.h"
				>
			</File>
			<File
				RelativePath="Lakey.h"
				>
			</File>
			<File
				RelativePath="LakeyMainWindow.h"
				>
			</File>
			<File
				RelativePath="LakeySetting.h"
				>
			</File>
			<File
				RelativePath="LaLabel.h"
				>
			</File>
			<File
				RelativePath="LaLine.h"
				>
			</File>
			<File
				RelativePath=".\LaNetwork.h"
				>
			</File>
			<File
				RelativePath="LaTuner.h"
				>
			</File>
			<File
				RelativePath="LaWaveCapture.h"
				>
			</File>
			<File
				RelativePath=".\LaWaveFile.h"
				>
			</File>
			<File
				RelativePath="MorseParser.h"
				>
			</File>
			<File
				RelativePath=".\mytest.h"
				>
			</File>
			<File
				RelativePath="Resource.h"
				>
			</File>
			<File
				RelativePath="SinSound.h"
				>
			</File>
			<File
				RelativePath="stdafx.h"
				>
			</File>
			<File
				RelativePath=".\WinIo.h"
				>
			</File>
		</Filter>
		<Filter
			Name="Դļ"
			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
			>
			<File
				RelativePath="Lakey.ico"
				>
			</File>
			<File
				RelativePath=".\lakey.ini"
				>
			</File>
			<File
				RelativePath="Lakey.rc"
				>
			</File>
			<File
				RelativePath="logo.bmp"
				>
			</File>
			<File
				RelativePath="mc.txt"
				>
			</File>
			<File
				RelativePath="small.ico"
				>
			</File>
		</Filter>
		<File
			RelativePath="ReadMe.txt"
			>
		</File>
		<File
			RelativePath=".\WinIo.lib"
			>
		</File>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>


================================================
FILE: src/Lakey.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{B20DFA3B-4DF4-464C-883D-940012A2178C}</ProjectGuid>
    <RootNamespace>Lakey</RootNamespace>
    <Keyword>Win32Proj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v142</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v142</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v142</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <Plat
Download .txt
gitextract_rhtqzxy4/

├── .project
├── LICENSE
├── README.md
├── bin/
│   ├── Lakey.v2.1.build.0019.Pencil/
│   │   ├── WINIO.VXD
│   │   ├── WinIo.sys
│   │   ├── lakey.ini
│   │   └── lakey_ZH.ini
│   └── Lakey.v2.2.build.0020.Paper/
│       ├── WINIO.VXD
│       └── WinIo.sys
├── doc/
│   └── index.html
└── src/
    ├── CommFunc.cpp
    ├── CommFunc.h
    ├── EventListener.cpp
    ├── EventListener.h
    ├── EventManagerWin32.cpp
    ├── EventManagerWin32.h
    ├── FFT.cpp
    ├── FFT.h
    ├── Graphics.cpp
    ├── Graphics.h
    ├── LaButton.cpp
    ├── LaButton.h
    ├── LaHwControl.cpp
    ├── LaHwControl.h
    ├── LaJournalPanel.cpp
    ├── LaJournalPanel.h
    ├── LaLabel.cpp
    ├── LaLabel.h
    ├── LaLine.cpp
    ├── LaLine.h
    ├── LaNetwork.cpp
    ├── LaNetwork.h
    ├── LaSpectrogram.cpp
    ├── LaSpectrogram.h
    ├── LaTuner.cpp
    ├── LaTuner.h
    ├── LaWaveCapture.cpp
    ├── LaWaveCapture.h
    ├── LaWaveFile.cpp
    ├── LaWaveFile.h
    ├── Lakey.aps
    ├── Lakey.h
    ├── Lakey.rc
    ├── Lakey.sln
    ├── Lakey.vcproj
    ├── Lakey.vcxproj
    ├── Lakey.vcxproj.filters
    ├── Lakey.vcxproj.user
    ├── LakeyMain.cpp
    ├── LakeyMainWindow.cpp
    ├── LakeyMainWindow.h
    ├── LakeySetting.cpp
    ├── LakeySetting.h
    ├── MorseParser.cpp
    ├── MorseParser.h
    ├── ReadMe.txt
    ├── Resource.h
    ├── SinSound.cpp
    ├── SinSound.h
    ├── UpgradeLog.XML
    ├── UpgradeLog2.XML
    ├── UpgradeLog3.XML
    ├── WINIO.VXD
    ├── WinIo.sys
    ├── html1.htm
    ├── lakey.ini
    ├── lakey_EN.ini
    ├── lakey_ZH.ini
    ├── mc.txt
    ├── mytest.cpp
    ├── mytest.h
    ├── resource.h
    ├── stdafx.cpp
    └── stdafx.h
Download .txt
SYMBOL INDEX (197 symbols across 33 files)

FILE: src/CommFunc.cpp
  function BOOL (line 12) | BOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen)
  function BOOL (line 23) | BOOL SetDlgItemDec(HWND hDlg, UINT nItemId, double val)
  function BOOL (line 36) | BOOL GetDlgItemDec(HWND hDlg, UINT nItemId, double* pVal)
  function BOOL (line 49) | BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, BYTE val)
  function BOOL (line 62) | BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, BYTE* pVal)
  function BOOL (line 77) | BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, WORD val)
  function BOOL (line 90) | BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, WORD* pVal)
  function BOOL (line 103) | BOOL GetDlgItemInt(HWND hDlg, UINT nItemId, int* pVal)

FILE: src/EventListener.h
  function class (line 5) | class IEventListener
  function class (line 9) | class IClickEventListener
  function class (line 15) | class IPaintEventListener
  function class (line 22) | class IMouseMoveEventListener
  function class (line 28) | class IKeyboardEventListener : public IClickEventListener
  function class (line 35) | class IMouseKeyEventListener : public IClickEventListener
  function class (line 45) | class ITimerEventListener
  function class (line 51) | class ICommandEventListener

FILE: src/EventManagerWin32.cpp
  function BOOL (line 15) | BOOL CEventDispatcherWin32::OnMessage(UINT message, WPARAM wParam, LPARA...
  function CGraphics (line 173) | CGraphics* CEventDispatcherWin32::NewGraphics(int w, int h)
  function BOOL (line 181) | BOOL CEventDispatcherWin32::EraseProc()
  function BOOL (line 187) | BOOL CEventDispatcherWin32::PaintProc()
  function BOOL (line 210) | BOOL CEventDispatcherWin32::MouseMoveProc(int x, int y)
  function BOOL (line 228) | BOOL CEventDispatcherWin32::KeyDownProc(int nKeyCode)
  function BOOL (line 241) | BOOL CEventDispatcherWin32::KeyUpProc(int nKeyCode)
  function BOOL (line 254) | BOOL CEventDispatcherWin32::MouseKeyDownProc(IMouseKeyEventControl::Mous...
  function BOOL (line 272) | BOOL CEventDispatcherWin32::MouseKeyUpProc(IMouseKeyEventListener::Mouse...
  function BOOL (line 290) | BOOL CEventDispatcherWin32::TimerProc(int nTimerId)
  function BOOL (line 303) | BOOL CEventDispatcherWin32::CommandProc(int nCommId)
  function BOOL (line 316) | BOOL IControl::PointInRect(const RECT* pRect, int x, int y)
  function BOOL (line 325) | BOOL IControl::IntersectRect(RECT* pDest, const RECT* pSrc1, const RECT*...

FILE: src/EventManagerWin32.h
  function class (line 10) | class IControl
  function class (line 28) | class IKeyboardEventControl : public IKeyboardEventListener
  function class (line 36) | class ITimerEventControl : public ITimerEventListener
  function class (line 40) | class ICommandEventControl : public ICommandEventListener
  function class (line 44) | class IUserData
  function class (line 51) | class IPaintableParent
  function class (line 58) | class CEventDispatcherWin32

FILE: src/Graphics.cpp
  function RECT (line 92) | const RECT* CGraphics::GetPaintRect()
  function HFONT (line 246) | HFONT CFont::GetFont()

FILE: src/Graphics.h
  type STYLE (line 7) | typedef struct tagSTYLE
  function class (line 15) | class CGraphics
  function class (line 60) | class CFont

FILE: src/LaButton.cpp
  function BOOL (line 55) | BOOL CLaButton::IsRelated(int x, int y)
  function BOOL (line 91) | BOOL CLaButton::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
  function BOOL (line 151) | BOOL CLaButton::OnKeyDown(void* owner, int nKeyCode)
  function BOOL (line 168) | BOOL CLaButton::OnKeyUp(void* owner, int nKeyCode)
  function BOOL (line 193) | BOOL CLaButton::OnMouseMove(void* owner, int x, int y)
  function BOOL (line 203) | BOOL CLaButton::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, in...
  function BOOL (line 215) | BOOL CLaButton::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
  function BOOL (line 240) | BOOL CLaButton::OnClick(void* owner)

FILE: src/LaButton.h
  type ButtonStyle (line 14) | typedef enum { BT_NORMAL, BT_LOCKABLE } ButtonStyle;
  function virtual (line 33) | virtual void SetUserData(void* pUserData) { m_pUserData = pUserData; }
  function virtual (line 34) | virtual void* GetUserData() { return m_pUserData; }
  function virtual (line 36) | virtual BOOL IsPressed() { return m_bIsDown; }
  function SetWantKeyCode (line 42) | void SetWantKeyCode(int nKeyCode) { m_nWantKeyCode = nKeyCode; }
  function GetWantKeyCode (line 43) | int GetWantKeyCode() { return m_nWantKeyCode; }

FILE: src/LaHwControl.cpp
  function BOOL (line 21) | BOOL CLaHwControl::OutByte(WORD nAddr, BYTE b)
  function BOOL (line 31) | BOOL CLaHwControl::GetState()

FILE: src/LaHwControl.h
  function class (line 3) | class CLaHwControl

FILE: src/LaJournalPanel.cpp
  function BOOL (line 30) | BOOL CLaJournalPanel::IsRelated(int x, int y)
  function BOOL (line 40) | BOOL CLaJournalPanel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)

FILE: src/LaLabel.cpp
  function BOOL (line 27) | BOOL CLaLabel::IsRelated(int x, int y)
  function BOOL (line 37) | BOOL CLaLabel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
  function BOOL (line 73) | BOOL CLaLabel::PushChar(char ch)

FILE: src/LaLabel.h
  function class (line 7) | class CLaLabel

FILE: src/LaLine.cpp
  function BOOL (line 31) | BOOL CLaLine::IsRelated(int x, int y)
  function BOOL (line 41) | BOOL CLaLine::OnPaint(void* owner, CGraphics* g, const RECT* pRect)

FILE: src/LaLine.h
  function class (line 5) | class CLaLine

FILE: src/LaNetwork.cpp
  function BOOL (line 66) | BOOL CLaNetwork::AppendStbSrcNode(const LANWSRCNODE* pStbSrc)
  function BOOL (line 97) | BOOL CLaNetwork::AppendNodeByAddr(const sockaddr* pAddr)
  function BOOL (line 112) | BOOL CLaNetwork::Startup(WORD nPort)
  function BOOL (line 150) | BOOL CLaNetwork::AppendKeyFrame(const LANWPKGKEYFRAME* pFrame)
  function BOOL (line 166) | BOOL CLaNetwork::PickKeyFrame(LANWPKGKEYFRAME* pFrame)
  function BOOL (line 189) | BOOL CLaNetwork::Bind(WORD nPort)
  function DWORD (line 210) | DWORD WINAPI CLaNetwork::NwRecvThreadProc(LPVOID pOwner)
  function DWORD (line 360) | DWORD WINAPI CLaNetwork::NwSendThreadProc(LPVOID pOwner)
  function BOOL (line 398) | BOOL CLaNetwork::SendKeyFrame(const char* pPkgBuff, int nLen, sockaddr_i...

FILE: src/LaNetwork.h
  type LANWPKGHEAD (line 42) | typedef struct
  type LANWPKGKEYFRAME (line 48) | typedef struct
  type LANWPKGSRCFRAME (line 55) | typedef struct
  type LANWPKGTXTFRAME (line 62) | typedef struct
  type LANWSRCNODEATTR (line 67) | typedef struct
  type LANWSRCNODE (line 75) | typedef struct tagLANWSRCNODE
  function class (line 83) | class INetworkEventListener
  function class (line 89) | class INetworkFrameListener
  function class (line 101) | class CLaNetwork

FILE: src/LaSpectrogram.cpp
  function BOOL (line 41) | BOOL CLaSpectrogram::Initialize()
  function BOOL (line 46) | BOOL CLaSpectrogram::IsRelated(int x, int y)
  function BOOL (line 56) | BOOL CLaSpectrogram::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
  function BOOL (line 134) | BOOL CLaSpectrogram::Refresh()
  function BOOL (line 167) | BOOL CLaSpectrogram::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int ...
  function BOOL (line 193) | BOOL CLaSpectrogram::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x,...

FILE: src/LaSpectrogram.h
  function virtual (line 31) | virtual BOOL OnClick(void* owner) { return FALSE; }

FILE: src/LaTuner.cpp
  function BOOL (line 47) | BOOL CLaTuner::IsRelated(int x, int y)
  function BOOL (line 65) | BOOL CLaTuner::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
  function BOOL (line 160) | BOOL CLaTuner::OnMouseMove(void* owner, int x, int y)
  function BOOL (line 165) | BOOL CLaTuner::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
  function BOOL (line 182) | BOOL CLaTuner::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
  function BOOL (line 201) | BOOL CLaTuner::OnTimer(void* owner, int nTimerId)

FILE: src/LaTuner.h
  type LASCALE (line 6) | typedef float	LASCALE;
  function class (line 8) | class ITunerEventListener
  function virtual (line 31) | virtual BOOL OnClick(void* owner) { return FALSE; }
  function LASCALE (line 38) | LASCALE GetScale() { return m_nScaleCurr; }

FILE: src/LaWaveCapture.cpp
  function BOOL (line 244) | BOOL CLaWaveCapture::Initialize()
  function BOOL (line 257) | BOOL CLaWaveCapture::IsRelated(int x, int y)
  function BOOL (line 267) | BOOL CLaWaveCapture::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
  function BOOL (line 423) | BOOL CLaWaveCapture::Refresh()
  function DWORD (line 598) | DWORD CLaWaveCapture::GetSyncPos(short int* pBuff, DWORD nBuffSize)
  function BOOL (line 630) | BOOL CLaWaveCapture::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int ...
  function BOOL (line 635) | BOOL CLaWaveCapture::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x,...

FILE: src/LaWaveCapture.h
  function class (line 27) | class ICwEventListener
  function virtual (line 54) | virtual BOOL OnClick(void* owner) { return FALSE; }
  function BOOL (line 64) | BOOL GetFrazeState() { return m_bFraze; }
  function SetFrazeState (line 65) | void SetFrazeState(BOOL bFraze) { m_bFraze = bFraze; }

FILE: src/LaWaveFile.h
  type LAAUDIOFILEHEADER (line 2) | typedef struct
  function class (line 25) | class CWaveFile

FILE: src/LakeyMain.cpp
  function _tWinMain (line 70) | int APIENTRY _tWinMain(HINSTANCE hInstance,
  function ATOM (line 126) | ATOM MyRegisterClass(HINSTANCE hInstance)
  function BOOL (line 157) | BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  function LRESULT (line 197) | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM ...
  function LRESULT (line 288) | LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP...
  function CalcSpeed (line 309) | void CalcSpeed(HWND hDlg)
  function UncalcSpeed (line 327) | void UncalcSpeed(HWND hDlg)
  function VOID (line 353) | VOID WINAPI OnSelChanged(HWND hDlg)
  function BOOL (line 392) | BOOL OnSettingsInit(HWND hDlg)
  function HostListAdd (line 435) | void HostListAdd(HWND hListCtrl, char* pHost, const char* pPort, int idx)
  function BOOL (line 448) | BOOL OnSettingPagesInit(HWND hDlg)
  function AddHost (line 520) | void AddHost(HWND hCtrl, HOSTNODE* pNode)
  function DelHost (line 538) | void DelHost(HWND hCtrl)
  function SaveTemp (line 545) | void SaveTemp(HWND hDlg)
  function DestroyCurrPage (line 595) | void DestroyCurrPage(HWND hTab)
  function OnSettingsAccept (line 607) | void OnSettingsAccept(HWND hDlg)
  function LRESULT (line 620) | LRESULT CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM...
  function INT_PTR (line 663) | INT_PTR CALLBACK SettingsPage(HWND hPage, UINT message, WPARAM wParam, L...
  function InitKochSample (line 763) | void InitKochSample()
  function LRESULT (line 784) | LRESULT CALLBACK CopyPad(HWND hDlg, UINT message, WPARAM wParam, LPARAM ...
  function LRESULT (line 964) | LRESULT CALLBACK TestDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM ...
  function PromptToWave (line 995) | void PromptToWave(HWND hWnd)
  function KochToWave (line 1003) | void KochToWave(HWND hWnd)
  function TextToAskWave (line 1013) | void TextToAskWave(char* pWavePathBuff, UINT nWavePathBuffSize, const ch...
  function TextToWave (line 1038) | void TextToWave(const char* pPathname, const char* pTxt, UINT nTxtLen, U...
  function LRESULT (line 1083) | LRESULT CALLBACK PromptProc(HWND hDlg, UINT message, WPARAM wParam, LPAR...

FILE: src/LakeyMainWindow.cpp
  function BOOL (line 240) | BOOL CLakeyMainWindow::OnTune(void* owner, LASCALE nScale)
  function MORSECODE (line 270) | MORSECODE* CLakeyMainWindow::GetMorseCode(char ch)
  function CLaTuner (line 283) | CLaTuner* CLakeyMainWindow::CreateTuner(const TUNERMAPPING* pMapping)
  function CLaTuner (line 288) | CLaTuner* CLakeyMainWindow::CreateTuner(const char* pText, int x, int y,...
  function CLaButton (line 306) | CLaButton* CLakeyMainWindow::CreateButton(const char* pText, int x, int ...
  function CLaButton (line 324) | CLaButton* CLakeyMainWindow::CreateButton(const BUTTONMAPPING* pMapping,...
  function CLaJournalPanel (line 329) | CLaJournalPanel* CLakeyMainWindow::CreateJournalPanel(const RECT* pRect,...
  function CLaWaveCapture (line 339) | CLaWaveCapture* CLakeyMainWindow::CreateWaveCapture(const RECT* pRect, I...
  function CLaSpectrogram (line 351) | CLaSpectrogram* CLakeyMainWindow::CreateSpectrogram(const RECT* pRect, I...
  function CLaLabel (line 361) | CLaLabel* CLakeyMainWindow::CreateLabel(const RECT* pRect, const char* p...
  function CLaLine (line 370) | CLaLine* CLakeyMainWindow::CreateLine(int x1, int y1, int x2, int y2)
  function BOOL (line 379) | BOOL CLakeyMainWindow::Initialize()
  function BOOL (line 412) | BOOL CLakeyMainWindow::OnPaint(void* owner, CGraphics* g, const RECT* pR...
  function BOOL (line 419) | BOOL CLakeyMainWindow::OnMouseMove(void* owner, int x, int y)
  function BOOL (line 424) | BOOL CLakeyMainWindow::OnKeyDown(void* owner, int nKeyCode)
  function BOOL (line 440) | BOOL CLakeyMainWindow::OnKeyUp(void* owner, int nKeyCode)
  function BOOL (line 460) | BOOL CLakeyMainWindow::OnMouseKeyDown(void* owner, MouseKeyType nMkt, in...
  function BOOL (line 484) | BOOL CLakeyMainWindow::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int ...
  function BOOL (line 513) | BOOL CLakeyMainWindow::ChooseSendFile()
  function BOOL (line 579) | BOOL CLakeyMainWindow::OnClick(void* owner)
  function BOOL (line 684) | BOOL CLakeyMainWindow::OnCommand(void* owner, int nCommId)
  function BOOL (line 722) | BOOL CLakeyMainWindow::NetworkStartup()
  function BOOL (line 752) | BOOL CLakeyMainWindow::StartEncryptTrng()
  function DWORD (line 900) | DWORD WINAPI CLakeyMainWindow::MorseQueueThreadProc(LPVOID pOwner)
  function DWORD (line 973) | DWORD WINAPI CLakeyMainWindow::MorseJournalThreadProc(LPVOID pOwner)
  function DWORD (line 993) | DWORD WINAPI CLakeyMainWindow::RecvMonitorThreadProc(LPVOID pOwner)

FILE: src/LakeyMainWindow.h
  function virtual (line 43) | virtual void NetworkShutdown() { return m_pNetwork->Shutdown(); }
  function virtual (line 45) | virtual BOOL IsRelated(int x, int y) { return TRUE; }

FILE: src/LakeySetting.cpp
  function BOOL (line 276) | BOOL CLakeySetting::Load()
  function BOOL (line 361) | BOOL CLakeySetting::Save()
  function calcStdWordLen (line 564) | float calcStdWordLen(short int nMorseCode, short int nMask)
  function wpmToParams (line 585) | void wpmToParams(WPMS* pWpms)
  function paramsToWpm (line 595) | void paramsToWpm(WPMS* pWpms)

FILE: src/LakeySetting.h
  type MORSECODE (line 17) | typedef struct tagMorseCode
  type BUTTONMAPPING (line 26) | typedef struct tagButtonMapping
  type TUNERMAPPING (line 36) | typedef struct tagTunerMapping
  type HOSTNODE (line 48) | typedef struct tagHostNode
  type vector (line 54) | typedef vector<HOSTNODE> HostList;
  type CUSTOMIZE (line 56) | typedef struct tagCustomize
  type WPMS (line 123) | typedef struct tagWPMS
  function class (line 137) | class CLakeySetting

FILE: src/MorseParser.h
  function class (line 5) | class IParseEventListener
  type MORSECODETREENODE (line 11) | typedef struct tagMorseCodeTreeNode
  function class (line 18) | class CMorseParser

FILE: src/SinSound.cpp
  function BOOL (line 55) | BOOL CSinSound::Initialize(HWND hWnd)
  function BOOL (line 69) | BOOL CSinSound::OnTimer(void* owner, int nTimerId)
  function BOOL (line 207) | BOOL CSinSound::InitBufferFormat()
  function BOOL (line 226) | BOOL CSinSound::InitPlayedBuffer()
  function BOOL (line 242) | BOOL CSinSound::WriteBuffer()
  function BOOL (line 379) | BOOL CSinSound::Validate()
  function LONG (line 406) | LONG CSinSound::GetVolume()
  function LONG (line 418) | LONG CSinSound::GetNoiseVolume()

FILE: src/SinSound.h
  type REAL (line 7) | typedef float			REAL;
  function class (line 9) | class CSinSound : public ITimerEventControl

FILE: src/mytest.cpp
  function BOOL (line 9) | BOOL GetDriveGeometry(DISK_GEOMETRY *pdg)
  function mytest (line 41) | int mytest()
Condensed preview — 74 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (410K chars).
[
  {
    "path": ".project",
    "chars": 198,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>lakey</name>\n\t<comment></comment>\n\t<projects>\n\t</proj"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 958,
    "preview": "# lakey\nLakey, a CW training tool.\n\nLakey是一款摩尔斯电码发报练习软件,具有摩尔斯电码解析、音频频谱分析、摩尔斯电码听抄练习、可进行多主机网络通联练习或试验等特点。\n\n![photo](./doc/i"
  },
  {
    "path": "bin/Lakey.v2.1.build.0019.Pencil/lakey.ini",
    "chars": 2343,
    "preview": "[CW]\r\nbeepfreq=1000.000000\r\nbeepvol=0.250000\r\nshorthit=80\r\nlonghit=240\r\nhitdelay=80\r\nletterdelay=240\r\nworddelay=240\r\n[GL"
  },
  {
    "path": "bin/Lakey.v2.1.build.0019.Pencil/lakey_ZH.ini",
    "chars": 2357,
    "preview": "[CW]\r\nbeepfreq=1000.000000\r\nbeepvol=0.250000\r\nshorthit=80\r\nlonghit=240\r\nhitdelay=80\r\nletterdelay=240\r\nworddelay=240\r\n[GL"
  },
  {
    "path": "doc/index.html",
    "chars": 21489,
    "preview": "<html>\r\n<head>\r\n<meta http-equiv=content-type content=\"text/html; charset=utf-8\">\r\n<title>Lakey 2.1 Pencil (Build 0019) "
  },
  {
    "path": "src/CommFunc.cpp",
    "chars": 2375,
    "preview": "#include \"stdafx.h\"\r\n#include \"Lakey.h\"\r\n#include \"windows.h\"\r\n#include \"Richedit.h\"\r\n#include \"commctrl.h\"\r\n#include <t"
  },
  {
    "path": "src/CommFunc.h",
    "chars": 518,
    "preview": "#pragma once\r\n\r\n#include \"stdlib.h\"\r\n\r\nBOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen);\r\nBOOL Se"
  },
  {
    "path": "src/EventListener.cpp",
    "chars": 49,
    "preview": "#include \"StdAfx.h\"\r\n#include \"EventListener.h\"\r\n"
  },
  {
    "path": "src/EventListener.h",
    "chars": 1164,
    "preview": "#pragma once\r\n\r\n#include \"Graphics.h\"\r\n\r\nclass IEventListener\r\n{\r\n};\r\n\r\nclass IClickEventListener\r\n{\r\npublic:\r\n\tvirtual "
  },
  {
    "path": "src/EventManagerWin32.cpp",
    "chars": 7821,
    "preview": "#include \"StdAfx.h\"\r\n#include \"eventmanagerwin32.h\"\r\n\r\nCEventDispatcherWin32::CEventDispatcherWin32(HWND hWnd)\r\n{\r\n\tm_hW"
  },
  {
    "path": "src/EventManagerWin32.h",
    "chars": 3254,
    "preview": "#pragma once\r\n\r\n#include <vector>\r\n\r\n#include \"Graphics.h\"\r\n#include \"EventListener.h\"\r\n\r\nusing namespace std;\r\n\r\nclass "
  },
  {
    "path": "src/FFT.cpp",
    "chars": 59,
    "preview": "#include \"StdAfx.h\"\r\n#include \"fft.h\"\r\n#include <complex>\r\n"
  },
  {
    "path": "src/FFT.h",
    "chars": 7150,
    "preview": "#pragma once\r\n\r\n#include <math.h>\r\n\r\n#ifdef PI\r\n#undef PI\r\n#endif\r\n\r\n#define PI\t\t3.1415926f\r\n\r\n/**\r\n * class T: unit of "
  },
  {
    "path": "src/Graphics.cpp",
    "chars": 6039,
    "preview": "#include \"StdAfx.h\"\r\n#include \"graphics.h\"\r\n#include \"stdio.h\"\r\n\r\nCGraphics::CGraphics(HWND hWnd)\r\n{\r\n\tm_hWnd = hWnd;\r\n\t"
  },
  {
    "path": "src/Graphics.h",
    "chars": 1743,
    "preview": "#pragma once\r\n\r\n#include <windows.h>\r\n\r\nclass CFont;\r\n\r\ntypedef struct tagSTYLE\r\n{\r\n\tint\t\tnColor;\r\n\tint\t\tnBgColor;\r\n\tint"
  },
  {
    "path": "src/LaButton.cpp",
    "chars": 5007,
    "preview": "#include \"StdAfx.h\"\r\n#include \"LaButton.h\"\r\n\r\nCLaButton::CLaButton(IPaintableParent* pParent, const char* pText, const R"
  },
  {
    "path": "src/LaButton.h",
    "chars": 2230,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n\r\nclass CLaButton \r\n\t: public IPaintEventControl\r\n\t, public IMouseMoveEv"
  },
  {
    "path": "src/LaHwControl.cpp",
    "chars": 604,
    "preview": "#include \"StdAfx.h\"\r\n\r\n#include \"LaHwControl.h\"\r\n//#include \"WinIo.h\"\r\n\r\nCLaHwControl::CLaHwControl(WORD nInitAddr, BYTE"
  },
  {
    "path": "src/LaHwControl.h",
    "chars": 249,
    "preview": "#pragma once\r\n\r\nclass CLaHwControl\r\n{\r\npublic:\r\n\tCLaHwControl(WORD nInitAddr, BYTE bInit);\r\n\t~CLaHwControl();\r\n\r\n\tBOOL O"
  },
  {
    "path": "src/LaJournalPanel.cpp",
    "chars": 4019,
    "preview": "#include \"StdAfx.h\"\r\n#include \"lajournalpanel.h\"\r\n\r\nCLaJournalPanel::CLaJournalPanel(IPaintableParent* pParent, const RE"
  },
  {
    "path": "src/LaJournalPanel.h",
    "chars": 966,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n#include \"MorseParser.h\"\r\n\r\nclass CLaJournalPanel\r\n\t: public IPaintEvent"
  },
  {
    "path": "src/LaLabel.cpp",
    "chars": 2154,
    "preview": "#include \"StdAfx.h\"\r\n#include \"LaLabel.h\"\r\n\r\n#include <assert.h>\r\n\r\nCLaLabel::CLaLabel(IPaintableParent* pParent, const "
  },
  {
    "path": "src/LaLabel.h",
    "chars": 777,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n\r\n#define MAX_LABEL_TEXT_LEN\t\t8193\r\n\r\nclass CLaLabel\r\n\t: public IPaintEv"
  },
  {
    "path": "src/LaLine.cpp",
    "chars": 803,
    "preview": "#include \"StdAfx.h\"\r\n#include \"LaLine.h\"\r\n\r\nCLaLine::CLaLine(IPaintableParent* pParent, int x1, int y1, int x2, int y2)\r"
  },
  {
    "path": "src/LaLine.h",
    "chars": 458,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n\r\nclass CLaLine\r\n\t: public IPaintEventControl\r\n{\r\npublic:\r\n\tCLaLine(IPai"
  },
  {
    "path": "src/LaNetwork.cpp",
    "chars": 9744,
    "preview": "#include \"StdAfx.h\"\r\n//#include \"winsock2.h\"\r\n//#include \"Ws2tcpip.h\"\r\n#include \"LaNetwork.h\"\r\n\r\n#define JOIN_SAFELY(ht)"
  },
  {
    "path": "src/LaNetwork.h",
    "chars": 3590,
    "preview": "#pragma once\r\n\r\n#define SEND_BUFF_BYTES\t\t128\r\n#define RECV_BUFF_BYTES\t\t128\r\n\r\n///ά֡/Ӧ֡\r\n#define LNPF_KEEPALIVE\t\t\t\t0x0000"
  },
  {
    "path": "src/LaSpectrogram.cpp",
    "chars": 4411,
    "preview": "#include \"StdAfx.h\"\r\n#include \"LaSpectrogram.h\"\r\n\r\nCLaSpectrogram::CLaSpectrogram(IPaintableParent* pParent, const RECT*"
  },
  {
    "path": "src/LaSpectrogram.h",
    "chars": 1762,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n#include \"FFT.h\"\r\n#include \"dsound.h\"\r\n\r\n//log(32768)\r\n//#define LOG_SAM"
  },
  {
    "path": "src/LaTuner.cpp",
    "chars": 6337,
    "preview": "#include \"StdAfx.h\"\r\n#include \"latuner.h\"\r\n#include \"FFT.h\"\r\n\r\nCLaTuner::CLaTuner(IPaintableParent* pParent, const char*"
  },
  {
    "path": "src/LaTuner.h",
    "chars": 2107,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n\r\n#define LA_TUNER_HEARTBEAT_TIMER_ID\t\t10060\r\ntypedef float\tLASCALE;\r\n\r\n"
  },
  {
    "path": "src/LaWaveCapture.cpp",
    "chars": 19072,
    "preview": "#include \"StdAfx.h\"\r\n#include \"lawavecapture.h\"\r\n#include \"sinsound.h\"\r\n\r\nCLaWaveCapture::CLaWaveCapture(IPaintableParen"
  },
  {
    "path": "src/LaWaveCapture.h",
    "chars": 3639,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n#include \"FFT.h\"\r\n#include \"dsound.h\"\r\n\r\n//log(32768)\r\n//#define LOG_SAM"
  },
  {
    "path": "src/LaWaveFile.cpp",
    "chars": 3903,
    "preview": "#include \"StdAfx.h\"\r\n#include \"stdio.h\"\r\n#include \"math.h\"\r\n#include \"assert.h\"\r\n#include \"LaWaveFile.h\"\r\n\r\n#define RESO"
  },
  {
    "path": "src/LaWaveFile.h",
    "chars": 980,
    "preview": "\r\ntypedef struct\r\n{\r\n\tDWORD\tnRiffFlag;\t\t//'RIFF'\r\n\tDWORD\tnCbSize;\r\n\tstruct\r\n\t{\r\n\t\tDWORD nWaveFlag;\t//'WAVE'\r\n\t\tDWORD nFm"
  },
  {
    "path": "src/Lakey.h",
    "chars": 39,
    "preview": "#pragma once\r\n\r\n#include \"resource.h\"\r\n"
  },
  {
    "path": "src/Lakey.rc",
    "chars": 17773,
    "preview": "// Microsoft Visual C++ generated resource script.\r\n//\r\n#include \"resource.h\"\r\n\r\n#define APSTUDIO_READONLY_SYMBOLS\r\n////"
  },
  {
    "path": "src/Lakey.sln",
    "chars": 1555,
    "preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 16\r\nVisualStudioVersion = 16.0.3"
  },
  {
    "path": "src/Lakey.vcproj",
    "chars": 7958,
    "preview": "<?xml version=\"1.0\" encoding=\"gb2312\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"8.00\"\r\n\tName=\"Lakey\""
  },
  {
    "path": "src/Lakey.vcxproj",
    "chars": 13836,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/Lakey.vcxproj.filters",
    "chars": 5315,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "src/Lakey.vcxproj.user",
    "chars": 141,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "src/LakeyMain.cpp",
    "chars": 29066,
    "preview": "// LakeyMain.cpp : Ӧóڵ㡣\r\n//\r\n\r\n#include \"stdafx.h\"\r\n#include \"Lakey.h\"\r\n#include \"windows.h\"\r\n#include \"Richedit.h\"\r\n#in"
  },
  {
    "path": "src/LakeyMainWindow.cpp",
    "chars": 26723,
    "preview": "#include \"StdAfx.h\"\r\n#include \"lakeymainwindow.h\"\r\n\r\n#include \"Mmreg.h\"\r\n#include \"dsound.h\"\r\n#include \"math.h\"\r\n#includ"
  },
  {
    "path": "src/LakeyMainWindow.h",
    "chars": 5282,
    "preview": "#pragma once\r\n\r\n#include <queue>\r\n\r\n#include \"EventManagerWin32.h\"\r\n#include \"LakeySetting.h\"\r\n#include \"LaWaveCapture.h"
  },
  {
    "path": "src/LakeySetting.cpp",
    "chars": 23653,
    "preview": "#include \"StdAfx.h\"\r\n#include \"lakeysetting.h\"\r\n\r\n#include \"stdio.h\"\r\n\r\n#define SetMorseCode(s, asc, mc, mm, kc)\t\\\r\n\ts.n"
  },
  {
    "path": "src/LakeySetting.h",
    "chars": 4402,
    "preview": "#pragma once\r\n\r\n#include <windows.h>\r\n#include <vector>\r\n#include \"LaTuner.h\"\r\n\r\nusing namespace std;\r\n\r\n#define MORSECO"
  },
  {
    "path": "src/MorseParser.cpp",
    "chars": 3140,
    "preview": "#include \"StdAfx.h\"\r\n#include \"morseparser.h\"\r\n\r\nCMorseParser::CMorseParser(const MORSECODE* pMorseList, int nCount, int"
  },
  {
    "path": "src/MorseParser.h",
    "chars": 994,
    "preview": "#pragma once\r\n\r\n#include \"LakeySetting.h\"\r\n\r\nclass IParseEventListener\r\n{\r\npublic:\r\n\tvirtual void OnWorkOut(void* owner,"
  },
  {
    "path": "src/ReadMe.txt",
    "chars": 1028,
    "preview": "========================================================================\r\n    WIN32 Ӧó : Lakey Ŀſ\r\n====================="
  },
  {
    "path": "src/Resource.h",
    "chars": 4366,
    "preview": "//{{NO_DEPENDENCIES}}\r\n// Microsoft Visual C++ generated include file.\r\n// Used by Lakey.rc\r\n//\r\n#define IDC_MYICON     "
  },
  {
    "path": "src/SinSound.cpp",
    "chars": 9313,
    "preview": "#include \"StdAfx.h\"\r\n#include \"dsound.h\"\r\n#include \"math.h\"\r\n#include \"sinsound.h\"\r\n\r\nstatic float DW = 0;\r\n\r\nCSinSound:"
  },
  {
    "path": "src/SinSound.h",
    "chars": 1727,
    "preview": "#pragma once\r\n\r\n#include \"EventManagerWin32.h\"\r\n\r\n#define PI\t\t\t\t3.1415926f\r\n#define PI2S\t\t\t2 * PI\r\ntypedef float\t\t\tREAL;"
  },
  {
    "path": "src/UpgradeLog.XML",
    "chars": 4319,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><"
  },
  {
    "path": "src/UpgradeLog2.XML",
    "chars": 2519,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><"
  },
  {
    "path": "src/UpgradeLog3.XML",
    "chars": 2328,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><"
  },
  {
    "path": "src/html1.htm",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/lakey.ini",
    "chars": 2342,
    "preview": "[CW]\r\nbeepfreq=1000.000000\r\nbeepvol=0.250000\r\nshorthit=80\r\nlonghit=240\r\nhitdelay=80\r\nletterdelay=240\r\nworddelay=240\r\n[GL"
  },
  {
    "path": "src/lakey_EN.ini",
    "chars": 2423,
    "preview": "[CW]\r\nbeepfreq=1000.000000\r\nbeepvol=0.250000\r\nshorthit=80\r\nlonghit=240\r\nhitdelay=80\r\nletterdelay=240\r\nworddelay=240\r\n[GL"
  },
  {
    "path": "src/lakey_ZH.ini",
    "chars": 2357,
    "preview": "[CW]\r\nbeepfreq=1000.000000\r\nbeepvol=0.250000\r\nshorthit=80\r\nlonghit=240\r\nhitdelay=80\r\nletterdelay=240\r\nworddelay=240\r\n[GL"
  },
  {
    "path": "src/mc.txt",
    "chars": 336,
    "preview": "A=10,VK_A\r\nB=0111\r\nC=0101\r\nD=011\r\nE=1\r\nF=1101\r\nG=001\r\nH=1111\r\nI=11\r\nJ=1000\r\nK=010\r\nL=1011\r\nM=00\r\nN=01\r\nO=000\r\nP=1001\r\nQ="
  },
  {
    "path": "src/mytest.cpp",
    "chars": 2259,
    "preview": "#include \"stdafx.h\"\r\n\r\n#include <windows.h>\r\n#include <winioctl.h>\r\n#include <stdio.h>\r\n\r\n#include \"mytest.h\"\r\n\r\nBOOL Ge"
  },
  {
    "path": "src/mytest.h",
    "chars": 15,
    "preview": "int mytest();\r\n"
  },
  {
    "path": "src/resource.h",
    "chars": 4264,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Lakey.rc\n//\n#define IDC_MYICON         "
  },
  {
    "path": "src/stdafx.cpp",
    "chars": 114,
    "preview": "// stdafx.cpp : ֻ׼ļԴļ\r\n// Lakey.pch ΪԤͷ\r\n// stdafx.obj ԤϢ\r\n\r\n#include \"stdafx.h\"\r\n\r\n// TODO:  STDAFX.H \r\n//κĸͷڴļ\r\n"
  },
  {
    "path": "src/stdafx.h",
    "chars": 571,
    "preview": "// stdafx.h : ׼ϵͳļİļ\r\n// dzõĵĿضİļ\r\n//\r\n\r\n#pragma once\r\n\r\n//#define WIN32_LEAN_AND_MEAN\t\t//  Windows ͷųʹõ\r\n// Windows ͷļ\r\n"
  }
]

// ... and 7 more files (download for full content)

About this extraction

This page contains the full source code of the idirect3d/lakey GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 74 files (337.5 KB), approximately 116.4k tokens, and a symbol index with 197 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!