--- /dev/null
+terminatorX - History
+All changes were done by me (Alexander Koenig) if not stated otherwise.
+
+[v2.3]
+- X-Window background fixed
+- wavfile overreading fixed by Andrew C. Bul+hac?k (acb@zikzak.net)
+- Using portable type definitions now where required. If you don't
+ have a <sys/types.h> on your system and your machines type sizes
+ equal those of an X86-machine you can specify -DUSE_X86_TYPES in
+ Makefile to compile without <sys/types.h>
+- Slight change in audiodevice-handling that fixes improper buffsize
+ settings on some soundcards (e.g. GUS)
+- Implemented "keep device open"-feature. Needs to be enabled via the
+ -DKEEP_DEV_OPEN switch in Makefile
+- Added some comments to the Makefile for easier editing
+- Added Big Endian support. Use -DBIG_ENDIAN_MACHINE for big endian hosts
+ like ultrapenguin suns or linux ppc. There's also -DBIG_ENDIAN_AUDIO
+ for big endian audio hardware (rare?) available, although proabably
+ nobody will need this.
+- Changed mix behaviour: Mix is now automatically turned on on startup if
+ the user has specified a proper loop file. (with the --loop or -l switch)
+- New mixing routine. You can now set the loop to scratch volume ratio with
+ the cursor keys (left/right). If you modify the volumes while recording
+ these action's will not be recorded. Saving happens with the currently
+ set level.
+- Fixed README-Bug said <m> instead of <x>
+
+[v2.2]
+- first released version
+- added colors. more standard use of X11.
+- added loop support.
+- added statusbar with mode/status display
+- added commandline options and help (on usage and keys)
+- added raw/mixed save scratch feature
+- added licmak to include license into binary
+- new handling of XAutoRepeat, only turned off now when SPACE pressed.
+- modified wave display (faster + nicer + incorrect (who cares anyway))
+- Makefile fixed by Adrian Reber (adreit00@fht-esslingen.de)
+- bug fixes
+
+[prerelease]
+
+[v2.1]
+- added recording, playback of recording functionality
+
+[v2.0]
+- moved from multithreaded to singlethreaded
+- position feedback
+- bug fixes
+
+[v1.0]
+- mouse support
+- no more position display due to pthread/X probs
+- bug fixes
+
+[v0.5]
+- first version
+- no mouse handling
+- accelerating vtt via sinus
+- multithreaded
+- sound aliasing
--- /dev/null
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) 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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. 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.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE 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.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <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 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision 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, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This 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 Library General
+Public License instead of this License.
--- /dev/null
+#terminatorX Makefile
+OBJECTS=turntable.o wav_read.o wav_write.o main.o tX.o endian.o
+
+#Correct the X11-Path if required
+INCLUDES=-I/usr/X11R6/include/
+LIBS=-L/usr/X11R6/lib -lX11 -lm
+
+#The tested big endian machines had problems
+#with opimized code if you own one of these
+#better leave this value the way it is -
+#On X86-machines it seems save to use:
+#OPT=-O2
+OPT=
+
+#Set the compiletime flags. Options:
+#-DUSE_CONSOLE Output information to the console (should be defined)
+#-DUSE_STOPSENSE If this is not defined terminatorX wil not
+# sense when mouse movement has stopped.
+#-DKEEP_DEV_OPEN Audiodevice will be kept open until
+# terminatorX exits
+#-DBIG_ENDIAN_MACHINE Use this on big endian machines (LinuxPPC, SUN, etc...)
+#-DBIG_ENDIAN_AUDIO Use this with big endian AUDIO HARDWARE (rare ?)
+# This IS NOT RELATED to BIG_ENDIAN_MACHINE
+#-DUSE_X86_TYPES Use this only IF you don't have <sys/types.h> AND a X86 machine
+#-DHANDLE_STOP If enabled generated audio data is "correct"
+# but introduces clicks
+#-DUSE_OLD_MIX re-enables old, bad, but proabably faster mixing routine
+CFLAGS=-DUSE_CONSOLE -DUSE_STOPSENSE -DHANDLE_STOP -Wall
+
+#Set the directory you want to install terminatorX in
+INSTALLDIR=/usr/local/bin
+
+#Set your compiler
+CC=egcs
+
+all: terminatorX
+
+install: terminatorX
+ cp terminatorX $(INSTALLDIR)
+
+clean: Makefile
+ rm -f $(OBJECTS) terminatorX core licmak licmak.o license.cc
+
+licmak.o: licmak.c
+ $(CC) -o licmak.o -c licmak.c
+
+licmak: licmak.o
+ $(CC) licmak.o -o licmak
+
+license.cc: COPYING licmak
+ ./licmak
+
+tX.o: tX.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o tX.o -c tX.cc
+
+main.o: main.cc license.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o main.o -c main.cc
+
+wav_read.o: wav_read.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o wav_read.o -c wav_read.cc
+
+wav_write.o: wav_write.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o wav_write.o -c wav_write.cc
+
+turntable.o: turntable.h turntable.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o turntable.o -c turntable.cc
+
+endian.o: endian.h endian.cc
+ $(CC) $(OPT) $(CFLAGS) $(INCLUDES) -o endian.o -c endian.cc
+
+terminatorX: $(OBJECTS)
+ $(CC) $(LIBS) $(OBJECTS) -o terminatorX
+
--- /dev/null
+terminatorX V2.3 README
+-----------------------
+
+Copyright (C) 1999 Alexander König
+eMail: alkoit00@fht-esslingen.de
+Homepage: http://www.termX.cjb.net
+
+This is open source software see the COPYING file that came with this
+distribution for details.
+
+Contens:
+--------
+
+ 1.......What it is
+ 2.......Quickstart
+ 3.......Features
+ 4.......Requirements
+ 5.......Installation
+ 6.......Operation
+ 7.......Further notes
+ 8.......Contact/Homepage
+
+1. What it is
+-------------
+
+TerminatorX is a realtime audio synthesizer. It enables you to scratch
+on wavfiles like you might have heard HipHop-DJs scratch on vinyl records.
+This is BETA Software please help me fix bugs. See section Contact/Homepage.
+Please read this README and take a look at the homepage
+http://www.termX.cjb.net BEFORE you complain.
+
+2. Quickstart:
+--------------
+
+ o tar xzf terminatorX-VXX.tar.gz
+ o cd terminatorX-VXX
+ o edit Makefile to your needs if required
+ (If you want to run terminatorX on a big endian machine (LinuxPPC,
+ Ultrapenguin SUN etc, enable -DBIG_ENDIAN_MACHINE (CFLAGS) and
+ disable optimizations (OPT=), on i386 machines you can safely use
+ OPT=-O2, set Compiler (default=egcs) and X-includes and libs)
+ o make
+ o become root
+ o make install
+ o become yourself
+ o start terminatorX with any 16Bit, 44.1 kHz, mono Wavfile:
+ e.g.: terminatorX anyfile.wav
+ o move your mouse pointer into terminatorX-Window
+ o press <RETURN> in the terminatorX-Window
+ o press and hold <SPACE>
+ o use your mouse to scratch
+ o release <SPACE> and if you enjoyed it press again.....
+ o press <RETURN> again to stop playback
+ o use <q> to quit
+
+3. Features:
+------------
+
+ o CD-Quality operation
+ o Audio aliasing
+ o Optional playback of an additional loop wavfile to
+ enable rhythm based scratching
+ o Recording of your scratching in a memory buffer, customizable by user
+ o Save that buffer (as a wavfile) with or without the loop mixed to it,
+ no matter whether you recorded it with our without a loop playback
+ o Visual feedback to "see" current position in scratch-wavfile
+ o Kernel-level audio latency configurable via parameters
+ o Run terminatorX on the hardware platform of your choice,
+ this software is known to run on the following platforms
+ - X86 (i386) (Linux)
+ - PowerPC (Linux)
+ - SUN Sparcs (Linux)
+ It should run on other Linux hardware as well, if you manage to
+ run it on any other platform (or you have prolems) please contact
+ me.
+
+4. Requirements:
+----------------
+
+ o A Linux system with gcc/egcs and X-Windows installed. Since
+ terminatorX is no longer multithreaded it shouldn't matter whether
+ you run it on glibc2 or libc5 system. I guess if your system
+ has more than let's say 100 BogoMIPS it should be capable
+ of running terminatorX (see --buffsize option for slow machines)
+ o A soundcard supported by OSS (Open Sound System, Linux Audio driver)
+ or any compatible audio driver.
+ o A good clean mouse and pad, a good X-Pointer setup. see the mouse
+ section on the homepage.
+
+Notes: On performance the only thing I can say is this: it runs fine on my
+ P(I)233MMX with 98MB of RAM. On slower machines you might have to
+ enlarge the kernel-level audio buffer (default is 512 Bytes) with
+ the -b (--buffsize) switch on invoking the program. Nobody ever
+ told me it didn't run (due to cpu-power) so if you think your machine's
+ to slow please tell me so I can specify machines to slow...
+
+5. Installation:
+----------------
+
+Installing terminatorX is pretty easy:
+- Extract the source-archive:
+ > tar xzf terminatorX-VXX.tar.gz
+
+- Change to the newly created directory
+ > cd terminatorX-VXX
+
+- Edit the Makefile:
+ The Makefile uses egcs as the default-compiler, if you don´t have egcs
+ installed you might want to set CC to gcc. On i386 (X86) machines you may
+ want to set some optimizations OPT=-O2 seems to work on any i386-System.
+ If you want to run terminatorX on a big endian machines (LinuxPPC, SUN, etc.)
+ set -DBIG_ENDIAN_MACHINE in the CFLAGS. Some of you might also have to
+ correct the path to X-includes and X-libs, and the INSTALLDIR.
+
+- Build the binary:
+ The normal
+ > make
+ should do it.
+
+- Install the binary:
+ Become root. This depends on your machine and user status. You don't
+ actually have to install the binary. You can run it from any directory.
+ If you have superuser access type:
+ > make install
+ and terminatorX will be installed into the INSTALLDIR you specified or
+ the default (/usr/local/bin).
+
+
+6. Operation:
+-------------
+
+For now terminatorX does not have a man-page but the most important information
+is contained within the binary:
+- run
+ > terminatorX --help
+ to see all commandline options
+- run
+ > terminatorX --keys
+ to see all key-commandos avialable in the terminatorX window.
+
+Using terminatorX is not as straightforward as you might expect it from an
+X-Window program. This is due to the fact that we abuse the mouse for scratching
+instead of using it to operate the software.
+
+Whenever you want to run terminatorX you have to give it one wavfile as
+an parameter (the file you want to scratch on):
+> terminatorX example.wav
+
+Most important command-line options:
+------------------------------------
+All options except for -h, -k, -g and -v require a parameter (X in the
+following descriptions). The following are just the most important options
+try -h to see ALL options.
+
+--help (or -h), no Parameter
+ Displays all options
+
+--keys (or -k), no Parameter
+ Displays all available keys in terminatorX's window.
+
+--mouse X (or -m) Parameter: float, Default: 0.5
+ Sets mouse sensitivity. Use negative values to invert scratch motion.
+
+--speed X (or -s) Parameter: float, Default: 1.0
+ Sets the motor speed of the virtual turntable.
+
+--loop X (or -l) Parameter: string, Default: none
+ Specifies a wavfile that can be played while you scratch on the main
+ wavfile. E.g. a beat if you want to scratch to a rythm. Mixing is
+ now automatically enabled if a loopfile was specified at startup,
+ use the <m>-key to toggle mix on/off.
+
+--prefix X (or -p) Prameter: string, Default: tX_scratch
+ Specifies the name of your saved scratches with the default these
+ files are called tX_scratch01.wav, tX_scratch02.wav ....
+
+--buffsize X (or -b) Parameter: integer, Default: 9
+ This configures the kernel-level audiobuffer's size. With
+ the default you get 2^9=512 Bytes. On slower systems you might
+ have to increase this value (10 -> 1024 Bytes, 11 -> 2048 Bytes ...)
+ The smaller this value the lower the latency of terminatorX.
+
+--recbuff X (or -r) Parameter: integer, Default: 500
+ With this option you can set the size of the recording buffer in KBytes.
+ Recording a scratch stops when this buffer is full. A 500 KB Buffer
+ equals 5.6 seconds of audio just like a same sized Wavfile of 16 Bit
+ 44.1 kHz mono.
+
+The keys in terminatorX (or how to use it)
+------------------------------------------
+
+After you started terminatorX it displays its own window with a figure of
+the scratch-wavfile and a "statusbar". If you press <RETURN> now the virtual
+turntable starts spinning and you see a red position display underneath the
+wave-data. If you press <SPACE> now and keep it pressed you put your
+"virtual" hand on the turntable, which means if you don't move your mouse
+playback seems to stop. If you DO move your mouse now (with <SPACE> still
+pressed) this movement will be transferred to the vritual turntable -> you
+scratch. When you release <SPACE> the motor of the virtual turntable starts
+spinning again and the playback continues at the usual rate (or the rate you
+set with the --speed parameter). Press <RETURN> again to stop playback.
+
+The following keys are only available when playback has stopped:
+
+<n> Enter SCRATCH mode: of the three mode-displays in the lower right
+ edge of the window the empty circle becomes activated.
+ This mode enables you to scratch when playback is activated as long
+ as you want. Nothing will be recorded.
+ Start/Stop scratching with <RETURN>
+
+<r> Enter RECORD mode: full circled becomes activated.
+ This mode enables the recording of your scratching when playback has
+ started. Playback will stop automatically when the recording buffer
+ is full.
+ Start/Stop recording with <RETURN>
+
+<p> Enter PLAYBACK mode: arrow becomes activated.
+ In this mode you can NOT scratch. This mode enables you to playback
+ your last recorded scratch.
+ Start/Stop playback with <RETURN>
+
+<m> Toggle mixing on/off (This works only if you loaded an additional
+ loop wavfile via the --loop option)
+ This option is fully functional with all three modes described above.
+ So you can record a scratch with the mix enabled and play it back
+ without.
+
+<LEFT> Decreases the scratch-volume and increases the loop-volume.
+
+<RIGHT> Decreases the loop-volume and increases the scratch-volume.
+
+<s> Saves the last scratch recorded RAW (not mixed with loop wavfile).
+ Filenames are generated automatically and can be influenced via
+ the --prefix option (see above).
+
+<x> Saves the last scratch recorded MIXED (mixed with loop wavfile).
+ Filenames are the same as with the <s> key. Mixing happens at
+ the currently set volume-levels.
+
+ATTENTION: Files are saved to the current directory. If there are files
+ of the same name already, these files will be overwritten!
+ So be sure to move your scratches to an other directory or
+ set a different prefix each time you save scratches.
+
+<q> Quits the program.
+
+Now have fun and scratch! If you have further question see homepage or send
+me an eMail.
+
+7. Further notes:
+-----------------
+
+You can find more on terminatorX operation and especially the mouse
+configuration on the terminatorX homepage: http://www.termX.cjb.net
+
+8. Contact/Homepage:
+--------------------
+
+terminatorX's homepage: http://www.termX.cjb.net
+
+If you wan't to send me comments, bug-reports, patches or scratches (see
+the users' scratches section on the terminatorX homepage) send a me
+an eMail to alkoit00@fht-esslingen.de
--- /dev/null
+TODO:
+
+These are the things I´d like to implement IF I have the time.
+The position of an idea in this list represents it´s priority:
+
+- correct getopt error handling.
+
+- Enhance audio quality with -DHANDLE_STOP -> no clicks.
+
+- Accept wavfiles that contain additional information (e.g. loops)
+
+- Support Y-mouse-movement for scratching
+
+- add a marker feature: this will allow you to set 12 markers visually
+ in the wavfile-display. These will be available via the F1-F12 keys in
+ NORMAL and RECORD mode. If you press (and hold) one of these keys it will
+ have the same effect as pressing space but if you release it it will
+ jump to the position you marked in the wavfile. Easier scratching for people
+ like me who don´t have any scratching skills.
+
+- implement licmak with either perl, awk or sed.
+
+- code cleanup: A lot of this code is ugly, e.g. writing to public member of
+ classes instead of calling a method. Or the position_update in render_block
+ I did this for easiness and speed. But it should be cleaned up I believe.
+
+DONE:
+
+The following stuff has been on the list above and is now ipmlemented:
+
+[V2.3] (use -DKEEP_DEV_OPEN in Makefile)
+
+- add a "keep device open" option and implement it
+ (this would help if you have problems opening device very often
+ due to memory fragmentation). And it would help me ;) as my card (or better
+ driver) clicks awfully when device is opened!
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: endian.cc
+
+ Description: swap byte order for big endian systems/audiohardware.
+*/
+
+
+#if defined (BIG_ENDIAN_MACHINE) || defined(BIG_ENDIAN_AUDIO) || defined (TEST_ENDIAN)
+
+#include "tX_types.h"
+
+void swap16(int16_t * val)
+{
+ int8_t temp;
+ int8_t *p;
+
+ p=(int8_t *) val;
+ temp=*p;
+ *p=*++p;
+ *p=temp;
+}
+
+void swap32(int32_t * val)
+{
+ /*
+ This one is very inefficient but it wont be
+ called from performace critical areas so
+ who cares...
+ */
+ int8_t temp;
+ int8_t *p;
+
+ p=(int8_t *) val;
+ temp=p[0];
+ p[0]=p[3];
+ p[3]=temp;
+
+ temp=p[1];
+ p[1]=p[2];
+ p[2]=temp;
+}
+
+void swapbuffer(int16_t *buffer, int samples)
+{
+ int i;
+ int8_t temp;
+ int8_t *p;
+ int16_t *val;
+
+ val=buffer;
+
+ for (i=0; i<samples; i++)
+ {
+ p=(int8_t *) val;
+ temp=*p;
+ *p=*++p;
+ *p=temp;
+ val++;
+ }
+}
+
+
+/* The following main() is just for testing */
+
+#ifdef TEST_ENDIAN
+
+#include <netinet/in.h>
+
+int main(int argc, char **argv)
+{
+ int16_t t16=0x1234;
+ int32_t t32=0x12345678;
+
+ int16_t buffer[8]={0x1234, 0x5678, 0x9ABC, 0xDEF0, 10, 20, 30, 0};
+
+ int i;
+
+ printf("16: %4x\n", (int) t16);
+ swap16(&t16);
+ printf("16: %4x\n", (int) t16);
+ swap16(&t16);
+ printf("16: %4x\n", (int) t16);
+ t16=htons(t16);
+ printf("16: %4x\n", (int) t16);
+ t16=htons(t16);
+ printf("16: %4x\n", (int) t16);
+
+ printf("32: %8x\n", (int) t32);
+ swap32(&t32);
+ printf("32: %8x\n", (int) t32);
+ swap32(&t32);
+ printf("32: %8x\n", (int) t32);
+ t32=htonl(t32);
+ printf("32: %8x\n", (int) t32);
+ t32=htonl(t32);
+ printf("32: %8x\n", (int) t32);
+
+ printf("buf: ");
+ for (i=0; i<8; i++) printf("%4hx ", buffer[i]);
+ swapbuffer(buffer, 8);
+ printf("\nbuf: ");
+ for (i=0; i<8; i++) printf("%4hx ", buffer[i]);
+ swapbuffer(buffer, 8);
+ printf("\nbuf: ");
+ for (i=0; i<8; i++) printf("%4hx ", buffer[i]);
+
+ puts("\nDone.\n");
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: endian.h
+
+ Description: header to endian.cc
+*/
+
+#if defined (BIG_ENDIAN_MACHINE) || defined(BIG_ENDIAN_AUDIO)
+
+#include "tX_types.h"
+
+extern void swap16(int16_t * val);
+extern void swap32(int32_t * val);
+extern void swapbuffer(int16_t *buffer, int samples);
+
+#endif
--- /dev/null
+/*
+ licmak - include a program's license into c/c++-code
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: licmak.c
+
+ Description: Turns COPYING into a C-String. This EXTREMELY ugly and
+ should be done with either perl, awk or sed. But I´m too lazy to learn
+ either one of these...
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+int main()
+{
+ FILE *in, *out;
+ char buffer[1024];
+ char outbuffer[2048];
+ char c;
+ int i,o;
+
+ in = fopen ("COPYING", "r");
+ if (!in)
+ {
+ puts("COPYING not found.");
+ return(1);
+ }
+
+ out = fopen ("license.cc", "w");
+ if (!out)
+ {
+ puts("failed to open license.cc");
+ return(1);
+ }
+
+ fprintf(out, "char license[]=\"\\\n");
+
+ while (!feof(in))
+ {
+ fgets(buffer, 1024, in);
+ if (!feof(in))
+ {
+ for (i=0, o=0; i<strlen(buffer); i++, o++)
+ {
+ c=buffer[i];
+
+ if (c=='"')
+ {
+ outbuffer[o]='\\';
+ o++;
+ }
+
+ outbuffer[o]=buffer[i];
+ }
+ outbuffer[o-1]=0;
+ strcat(outbuffer, "\\n\\\n");
+ /*
+ outbuffer[o-1]='\\';
+ outbuffer[o]='\n';
+ outbuffer[o+1]=0;
+ */
+ fprintf(out, "%s", outbuffer);
+ }
+ }
+ fprintf(out, "\";\n");
+ return(0);
+}
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: main.cc
+
+ Description: This contains the main() function. All the initializing
+ happens here:
+ - Commandline parsing
+ - Loading of loop and scratch wavfiles
+ - Creating of one instance of tX_Window and one of Virtual_Turntable
+ - Running of the event loop in tX_Window
+
+ Changes:
+
+ 19 Mar 1999: Applied a patch by Andrew C. Bul+hac?k (eMail: acb@zikzak.net)
+ that fixes wavfile reading routine for the overreading bug.
+
+ 20 Mar 1999: Big endian support.
+
+ 23 Mar 1999: display of new keys (<-, ->)
+*/
+#include <stdio.h>
+#include "wav_file.h"
+#include "turntable.h"
+#include "tX.h"
+#include <malloc.h>
+#include <math.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "endian.h"
+#include "tX_types.h"
+#include "version.h"
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+Virtual_TurnTable *myvtt;
+tX_Window *mywin;
+
+#include "license.cc"
+
+/* glob_parm: struct for global parameters */
+
+typedef struct glob_parm
+{
+ float mouse_speed; // -m, --mouse
+ char s_wav[256]; // no_opt
+ char m_wav[256]; // -l, --loop
+ char prefix[128]; // -p, --prefix
+ char dev_name[128]; // -d, --device
+ int buff_no; // -n, --buffno
+ int buff_size; // -b, --buffsize
+ int rec_size; // -t, --rectime
+ int stop_sense_cycles; // -c, --sensecycles
+ int verbose;
+ int warp_border; // -w, --warp
+ int width; // -x, --width
+ int height; // -y, --height
+ float vtt_default_speed; // -s, --speed
+} glob_parm;
+
+glob_parm parms;
+
+/* set_defaults(): sets defaults in parms struct */
+
+void set_defaults()
+{
+ parms.mouse_speed=0.5;
+ strcpy(parms.s_wav, "");
+ strcpy(parms.m_wav, "");
+ strcpy(parms.prefix, "tX_scratch");
+ strcpy(parms.dev_name, "/dev/dsp");
+
+ parms.buff_no=2;
+ parms.buff_size=9;
+
+ parms.rec_size=512000;
+ parms.stop_sense_cycles=3;
+ parms.vtt_default_speed=1.0;
+ parms.verbose=0;
+ parms.warp_border=200;
+ parms.height=600;
+ parms.width=1000;
+}
+
+/* usage(): displays parameters */
+
+void usage()
+{
+ puts("usage: terminatorX [options] wavfile\n");
+ puts("options:");
+ puts("[short] [long] [type] [default] [description]");
+ puts("-m --mouse float 0.5 mouse sensitivity");
+ puts("-l --loop string - loop wavfile");
+ puts("-p --prefix string tX_scratch recfile prefix");
+ puts("-d --device string /dev/dsp audio output device");
+ puts("-n --buffno integer 2 number of audio buffers");
+ puts("-b --buffsize integer 9 size of audio buffers (2^size)");
+ puts("-r --recbuff integer 500 size of record buffer in KB");
+ puts("-c --sensecycles integer 3 cycles to mouse stop sense");
+ puts("-s --speed float 1.0 speed of turntable motor");
+ puts("-w --warp integer 200 border for mouse warp");
+ puts("-x --width integer 1000 window width");
+ puts("-y --height integer 600 window height");
+ puts("-v --verbose verbose output");
+ puts("-k --keys display window keys");
+ puts("-h --help this page");
+ puts("-g --license display license (GPL V2)");
+}
+
+/* keys(): display available keys in Window */
+
+void keys()
+{
+ puts("Available keys in terminatorX:\n");
+ puts("[key] [description]");
+ puts("<RETURN> start/stop playback");
+ puts("<SPACE> activate mouse when playback active (to scratch)");
+ puts(" pressed: hand on turntable");
+ puts(" released: hand off turntable");
+ puts(" symbol: lower right red rectangle");
+ puts("<n> switch to \"normal\" scratch mode (no recording)");
+ puts(" symbol: empty circle. mouse active.");
+ puts("<r> switch to record mode. playback stops when record buffer is full.");
+ puts(" symbol: full circle. mouse active.");
+ puts("<p> switch to playback mode. plays the recorded scratch.");
+ puts(" symbol: arrow. mouse inactive");
+ puts("<m> toggle mixing of loop on/off");
+#ifndef USE_OLD_MIX
+ puts("<LEFT> increase loop volume, decrease scratch volume");
+ puts("<RIGHT> increase scratch volume, decrease loop volume");
+#endif
+ puts("<s> save RAW scratch to wavfile");
+ puts("<x> save MIXED scratch to wavfile");
+ puts("<q> exit terminatorX\n");
+ puts("Saving, mode changes and mix toggles are only available when playback has stopped.");
+}
+
+/* parse_cd: parses the commandline using getopt
+
+ this could use some more error checking.
+*/
+
+void parse_cmd(int argc, char **argv)
+{
+ int c;
+
+ /* make -Wall shut up */
+ // int digit_optind = 0;
+
+ set_defaults();
+
+ while (1)
+ {
+ /* make -Wall shut up */
+ // int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"mouse", 1, 0, 'm'},
+ {"loop", 1, 0, 'l'},
+ {"prefix", 1, 0, 'p'},
+ {"device", 1, 0, 'd'},
+ {"buffno", 1, 0, 'n'},
+ {"buffsize", 1, 0, 'b'},
+ {"recbuff", 1, 0, 'r'},
+ {"sensecycles", 1, 0, 'c'},
+ {"speed", 1, 0, 's'},
+ {"verbose", 1, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"warp", 1, 0, 'w'},
+ {"height", 1, 0, 'y'},
+ {"width", 1, 0, 'x'},
+ {"keys", 0, 0, 'k'},
+ {"license", 0, 0, 'g'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "m:l:p:d:n:b:r:c:s:vkhgw:x:y:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'm':
+ sscanf(optarg, "%f", &parms.mouse_speed);
+ break;
+
+ case 'l':
+ strcpy(parms.m_wav, optarg);
+ break;
+
+ case 'p':
+ strcpy(parms.prefix, optarg);
+ break;
+
+ case 'd':
+ strcpy(parms.dev_name, optarg);
+ break;
+
+ case 'n':
+ sscanf(optarg, "%i", &parms.buff_no);
+ break;
+
+ case 'b':
+ sscanf(optarg, "%i", &parms.buff_size);
+ break;
+
+ case 'r':
+ sscanf(optarg, "%i", &parms.rec_size);
+ parms.rec_size*=1024;
+ break;
+
+ case 'c':
+ sscanf(optarg, "%i", &parms.stop_sense_cycles);
+ break;
+
+ case 's':
+ sscanf(optarg, "%f", &parms.vtt_default_speed);
+ break;
+
+ case 'v':
+ parms.verbose=1;
+ break;
+
+ case 'h':
+ usage();
+ exit(0);
+ break;
+
+ case 'k':
+ keys();
+ exit(0);
+ break;
+
+ case 'w':
+ sscanf(optarg, "%i", &parms.warp_border);
+ break;
+
+ case 'x':
+ sscanf(optarg, "%i", &parms.width);
+ break;
+
+ case 'y':
+ sscanf(optarg, "%i", &parms.height);
+ break;
+
+ case 'g':
+ puts(license);
+ exit(0);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind != argc-1)
+ {
+ puts("Error: You must specify one WAV-file you want to scratch on.\n");
+ usage();
+ exit(1);
+ }
+ else
+ {
+ strcpy(parms.s_wav, argv[optind]);
+ }
+
+
+ if (parms.verbose)
+ {
+ printf("Mouse speed : %f\n", parms.mouse_speed);
+ printf("Wavefile : %s\n", parms.s_wav);
+
+ if (strlen(parms.m_wav))
+ printf("Loop wavefile : %s\n", parms.m_wav);
+ else puts("No loop file.");
+
+ printf("Rec-prefix : %s\n", parms.prefix);
+ printf("Device : %s\n", parms.dev_name);
+ printf("Audio-Buffers : %i\n", parms.buff_no);
+ printf("Size : %i (%i Bytes)\n", parms.buff_size, 1 << parms.buff_size);
+ printf("Recbuffsize : %i (%f Seconds)\n", parms.rec_size, ((float) parms.rec_size) / 88200.0);
+ printf("Stopsensecycles : %i\n", parms.stop_sense_cycles);
+ printf("VTT speed : %f\n", parms.vtt_default_speed);
+ printf("Warp border : %i\n", parms.warp_border);
+ printf("Window height : %i\n", parms.height);
+ printf("Window width : %i\n", parms.width);
+ }
+}
+
+/* load_wav(): load a wavfile with filename name.
+ writes size of file to *size, and
+ returns a pointer to the loaded wave-data.
+*/
+
+int16_t *load_wav(char *name, unsigned int *size)
+{
+ wav_sig wav_in;
+ int16_t *data;
+ int16_t *p;
+ ssize_t allbytes=0;
+ ssize_t bytes=0;
+ int i;
+
+ if (!init_wav_read(name, &wav_in))
+ {
+#ifdef USE_CONSOLE
+ printf("[load_wav] Error. Couldn't open \"%s\".\n", name);
+#endif
+ }
+
+#ifdef USE_CONSOLE
+ printf("Loading: %s\n", name);
+ if (parms.verbose) printf("File: %i Bytes Data, %i Bit Depth, %i Hz Samplerate.\n", wav_in.len, wav_in.depth, wav_in.srate);
+#endif
+
+ if (wav_in.depth != 16)
+ {
+#ifdef USE_CONSOLE
+ puts("[load_wav] Error: Wave-File is not 16 Bit. Fatal. Giving up.");
+#endif
+ exit(1);
+ }
+
+ if (wav_in.chans != 1)
+ {
+#ifdef USE_CONSOLE
+ puts("[load_wav] Error: Wave-File is not Mono. Fatal. Giving up.");
+#endif
+ exit(2);
+ }
+
+#ifdef USE_CONSOLE
+ if (wav_in.srate != 44100)
+ {
+ puts("[load_wav] Warning: Wave-File was not recorded at 44.100 Hz!");
+ }
+ if (wav_in.blkalign != 2)
+ {
+ printf("[load_wav] Warning: Unexpected block alignment: %i.\n", wav_in.blkalign);
+ }
+#endif
+
+ *size=wav_in.len;
+ data = (int16_t *) malloc (*size);
+
+ if (!data)
+ {
+#ifdef USE_CONSOLE
+ puts("[load_wav] Error: Failed to allocate sample memory. Fatal. Giving up.");
+ exit(3);
+#endif
+ }
+
+ p=data;
+
+
+ while (wav_in.len>allbytes)
+ {
+ bytes = read(wav_in.handle, p, min(1024, wav_in.len-allbytes));
+#ifdef BIG_ENDIAN_MACHINE
+ swapbuffer(p, bytes/sizeof(int16_t));
+#endif
+
+ if (bytes<=0)
+ {
+#ifdef USE_CONSOLE
+ puts("[load_wav] Error: Failed to read Wave-Data (Corrupt?). Fatal. Giving up.");
+ if(bytes<0) perror("terminatorX");
+#endif
+ exit(4);
+ }
+
+ allbytes+=bytes;
+
+ for (i=0; i<bytes; i+=2) p++;
+ }
+
+ close(wav_in.handle);
+
+#ifdef USE_CONSOLE
+ if (parms.verbose) printf("Read: %i Bytes of Wave-Data.\n", allbytes);
+#endif
+ return(data);
+}
+
+/* main(): */
+
+int main(int argc, char **argv)
+{
+
+ int16_t *data_in;
+ unsigned int size_in;
+
+ int16_t *beat_data;
+ unsigned int beat_size;
+
+ int16_t *recordbuffer;
+
+ TT_init init_data;
+
+ printf("%s, Copyright (C) 1999 Alexander König, alkoit00@fht-esslingen.de\n", VERSIONSTRING);
+ puts("terminatorX comes with ABSOLUTELY NO WARRANTY; for details use option --license");
+ puts("This is free software, and you are welcome to redistribute it");
+ puts("under certain conditions; see option --license\n");
+
+ parse_cmd(argc, argv);
+
+ data_in = load_wav(parms.s_wav, &size_in);
+
+ if (strlen(parms.m_wav))
+ {
+ beat_data = load_wav(parms.m_wav, &beat_size);
+ }
+ else
+ {
+ beat_data = NULL; beat_size=0;
+ }
+
+#ifdef USE_CONSOLE
+ if (parms.verbose) printf("Allocating Recorder buffer of %i Bytes.\n", parms.rec_size);
+#endif
+ recordbuffer=(int16_t *) malloc(parms.rec_size);
+
+ if (!recordbuffer)
+ {
+#ifdef USE_CONSOLE
+ puts("[main] Error: Allocate Recorder buffer. Fatal. Giving up.");
+#endif
+ exit(1);
+ }
+
+ init_data.speed=(f_prec) parms.vtt_default_speed;
+ init_data.default_speed=(f_prec) parms.vtt_default_speed;
+ init_data.buff_cfg=(parms.buff_no<<16) | parms.buff_size;
+ init_data.bsize=1<<parms.buff_size;
+ init_data.verbose=parms.verbose;
+ init_data.playback_data=data_in;
+ init_data.playback_size=size_in;
+ init_data.record_data=recordbuffer;
+ init_data.record_size=parms.rec_size;
+ init_data.mix_data=beat_data;
+ init_data.mix_size=beat_size;
+
+ strcpy(init_data.file_name, parms.prefix);
+ strcpy(init_data.devicename, parms.dev_name);
+
+ myvtt=new Virtual_TurnTable(&init_data);
+
+ mywin=new tX_Window(myvtt, parms.width, parms.height, parms.warp_border, parms.stop_sense_cycles, parms.mouse_speed, parms.verbose, parms.s_wav, parms.m_wav);
+ myvtt->set_window(mywin);
+
+ mywin->prepare_data_display(data_in, size_in);
+
+ mywin->loop();
+
+ free(recordbuffer);
+ free(data_in);
+
+ puts("Have a nice life.");
+}
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: tX.cc
+
+ Description: Does all the X-Handling.
+
+ Comment: I know NOTHING about X11. All of the code I wrote here is
+ derived from the X-includes and man pages. So assume this is full of
+ bad X-Handling. Like all of my code this is: HACKED TO WORK NOT TO BE NICE
+ If you can make it better please do so.
+
+ Changes:
+
+ 20 Mar 1999 - Fixed a bug that made terminatorX appear with a partly
+ white background on a sun remote x-display.
+
+ 20 Mar 1999 - moved short to int16_t
+
+ 23 Mar 1999 - support for new mixing in Virtual_Turntable
+*/
+
+#include "tX.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "version.h"
+char title[]=VERSIONSTRING;
+
+#include "tX_types.h"
+
+#define BORDER_ALIGN 5
+#define TOOLBAR_SIZE 20
+
+#define DC DefaultColormap(disp, DefaultScreen(disp))
+
+/* tX_Window::tx_Window() : intializes tX_Window, connects to X-Server, and creates Window */
+
+tX_Window :: tX_Window(Virtual_TurnTable *vttptr, int sizex, int sizey, int warp, int cycles, f_prec mspeed, int verb, char *sname, char *lname)
+{
+ XColor dummy;
+
+ verbose=verb;
+ mouse_speed=mspeed;
+
+ vtt=vttptr;
+
+ playback_active=0;
+
+ width = sizex;
+ height = sizey;
+
+ mouse_border=warp;
+
+ strcpy(s_name, sname);
+ if (strlen(s_name)>20)
+ {
+ s_name[18]='.';
+ s_name[19]='.';
+ s_name[20]='.';
+ s_name[21]=0;
+ }
+ strcpy(l_name, lname);
+ if (strlen(l_name)>20)
+ {
+ l_name[18]='.';
+ l_name[19]='.';
+ l_name[20]='.';
+ l_name[21]=0;
+ }
+
+ if (width < 3*mouse_border)
+ {
+#ifdef USE_CONSOLE
+ puts("[tX] Error. Window with should be at least 3 times the warp border.");
+#endif
+ exit(5);
+ }
+
+ sense_cycles=cycles;
+
+ medx=width/2;
+ medy=height/2;
+
+ quit=0;
+ motor_on=1;
+
+ warpx_min=mouse_border;
+ warpx_max=width-mouse_border;
+ ptrwarped=0;
+
+#ifdef USE_CONSOLE
+ if (verbose) puts("[tX] Initializing.");
+#endif
+ disp=XOpenDisplay(NULL);
+
+ if (!disp)
+ {
+#ifdef USE_CONSOLE
+ puts("[tX] Error: Failed to connect to default display. Fatal. Giving up.");
+#endif
+ exit(1);
+ }
+
+ win=XCreateSimpleWindow(disp, DefaultRootWindow(disp), 0,0, width, height,0,0,0);
+ gc=XCreateGC(disp, win, GCBackground | GCForeground, &xgcv);
+ XMapWindow(disp, win);
+ XStoreName(disp,win,title);
+
+ event_mask = KeyReleaseMask | KeyPressMask | PointerMotionMask | ExposureMask;
+
+ XSelectInput(disp,win,event_mask);
+
+ XSync(disp,False);
+
+ xkeyev=(XKeyEvent *) &xev;
+ xmotev=(XMotionEvent *) &xev;
+
+ XAllocNamedColor(disp, DC, "green", &col_data, &dummy);
+ XAllocNamedColor(disp, DC, "grey", &col_frame, &dummy);
+ XAllocNamedColor(disp, DC, "red", &col_pos, &dummy);
+ XAllocNamedColor(disp, DC, "yellow", &col_marker, &dummy);
+ XAllocNamedColor(disp, DC, "orange", &col_activebtn, &dummy);
+ XAllocNamedColor(disp, DC, "grey", &col_inactivebtn, &dummy);
+
+ black=BlackPixel(disp, DefaultScreen(disp));
+ white=WhitePixel(disp, DefaultScreen(disp));
+
+ font = XLoadFont(disp, "fixed");
+ if (font)
+ {
+#ifdef USE_CONSOLE
+ if (verbose) puts("[tX] Font loaded.");
+#endif
+ XSetFont(disp, gc, font);
+ }
+
+}
+
+/* tX_Window::prepare_data_display(): calculates values necessary for data diplay. */
+
+void tX_Window :: prepare_data_display(int16_t *data, unsigned int size)
+{
+ data_disp_x=BORDER_ALIGN;
+ data_disp_y=BORDER_ALIGN;
+
+ data_disp_width=width-2*BORDER_ALIGN;
+ data_disp_height=height-3*BORDER_ALIGN-TOOLBAR_SIZE;
+
+ data_samples=size/2;
+ data_ptr=data;
+
+ samples_per_pixel=data_samples/width;
+ y0=data_disp_y+data_disp_height/2;
+
+ pos_y=data_disp_y+data_disp_height+BORDER_ALIGN;
+ pos_max_x=data_disp_x+data_disp_width;
+
+ modex=width-3*(TOOLBAR_SIZE)-BORDER_ALIGN;
+ modey=height-TOOLBAR_SIZE;
+ bt_w=TOOLBAR_SIZE-BORDER_ALIGN;
+ bt_h=bt_w;
+ bt_a=BORDER_ALIGN;
+ modex-=2*(bt_w+bt_a);
+}
+
+/* tX_Window::display-data(): actually displays the wave-data */
+
+void tX_Window :: display_data()
+{
+ int sample;
+ int16_t value;
+ int x,y1;
+ f_prec temp;
+ f_prec half_data_height;
+
+ half_data_height = (f_prec) data_disp_height/2;
+
+ XSetForeground(disp, gc, col_frame.pixel);
+ XDrawRectangle(disp, win, gc, data_disp_x, data_disp_y, data_disp_width, data_disp_height);
+
+ XSetForeground(disp, gc, col_data.pixel);
+
+ for (x=0; x<data_disp_width; x++)
+ {
+ value=data_ptr[x*samples_per_pixel];
+ for (sample=x*samples_per_pixel; sample<(x+1)*samples_per_pixel; sample++)
+ {
+ value=(value+data_ptr[sample])/2;
+ }
+ temp=((f_prec) value)/32767.0;
+ y1=(int) (temp * half_data_height);
+ XDrawLine(disp, win, gc, data_disp_x+x, y0-y1, data_disp_x+x, y1+y0);
+ }
+ XSync(disp, False);
+}
+
+/* tX_Window::set_pos() : updates the (sample-)position display to position pos
+
+ If SLIM_POS is defined set_pos() draws lines instead of rectangles.
+ Might be slightly faster (and uglier).
+*/
+
+void tX_Window :: set_pos(int pos)
+{
+#ifdef SLIM_POS
+ pos+=BORDER_ALIGN;
+
+ XSetForeground(disp, gc, col_pos.pixel);
+ XDrawLine(disp, win, gc, data_disp_x, pos_y, pos, pos_y);
+
+ XSetForeground(disp, gc, black);
+ XDrawLine(disp, win, gc, pos, pos_y, pos_max_x, pos_y);
+#else
+ XSetForeground(disp, gc, col_pos.pixel);
+ XFillRectangle(disp, win, gc, data_disp_x, pos_y-1, pos-2*BORDER_ALIGN, 3);
+
+ XSetForeground(disp, gc, black);
+ XFillRectangle(disp, win, gc, pos+BORDER_ALIGN, pos_y-1, pos_max_x-pos, 3);
+#endif
+}
+
+/* tX_Window::get_samples_per_pixel() : returns value calculated in prepare_data_display()*/
+
+int tX_Window :: get_samples_per_pixel()
+{
+ return(samples_per_pixel);
+}
+
+#include <X11/keysym.h>
+
+/* tx_Window::handle_KeyPress() : Evaluates xkeyev as KeyPress Event */
+
+void tX_Window :: handle_KeyPress()
+{
+ KeySym key;
+
+ key=XKeycodeToKeysym (disp, xkeyev->keycode, 0);
+
+ switch (key)
+ {
+ case XK_Return:
+ {
+ if (playback_active)
+ {
+ playback_active=0;
+ vtt->needle_up();
+ if (vtt->mode == MODE_RECORD_SCRATCH)
+ {
+ vtt->store_rec_pos();
+ }
+ set_pos(0);
+ display_action();
+ }
+ else
+ {
+ playback_active=1;
+ vtt->speed=vtt->default_speed;
+ vtt->needle_down();
+ if (vtt->mode == MODE_RECORD_SCRATCH)
+ {
+ vtt->reset_rec_pos();
+ }
+ display_action();
+ }
+ }
+ break;
+
+ case XK_space:
+ {
+ XAutoRepeatOff(disp);
+ vtt->speed=0;
+ XGrabPointer(disp, win, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XWarpPointer(disp, win, win, 0, 0, 0, 0, medx, medy);
+ mx=medx;
+ first_mot_event=1;
+ mtime=CurrentTime;
+ motor_on=0;
+ }
+ break;
+
+ case XK_q:
+ {
+ if (playback_active)
+ {
+ vtt->needle_up();
+ playback_active=0;
+ XUngrabPointer(disp, CurrentTime);
+ }
+ XAutoRepeatOn(disp);
+ XSync(disp, False);
+ quit=1;
+ }
+ break;
+
+ case XK_n:
+ {
+ if (!playback_active)
+ {
+ vtt->set_mode(MODE_SCRATCH);
+ display_mode();
+ }
+ }
+ break;
+
+ case XK_r:
+ {
+ if (!playback_active)
+ {
+ vtt->set_mode(MODE_RECORD_SCRATCH);
+ display_mode();
+ }
+ }
+ break;
+
+ case XK_p:
+ {
+ if (!playback_active)
+ {
+ vtt->set_mode(MODE_PLAYBACK_RECORDED);
+ display_mode();
+ }
+ }
+ break;
+
+ case XK_m:
+ if (!playback_active)
+ {
+ vtt->toggle_mix();
+ display_text();
+ }
+ break;
+
+ case XK_s:
+ if (!playback_active)
+ {
+ vtt->save(0);
+ display_text();
+ }
+ break;
+
+ case XK_x:
+ if (!playback_active)
+ {
+ vtt->save(1);
+ display_text();
+ }
+ break;
+
+#ifndef USE_OLD_MIX
+ case XK_Left:
+ if (vtt->vol_loop < 1.0)
+ {
+ vtt->vol_loop+=0.01;
+ vtt->vol_scratch=1.0-vtt->vol_loop;
+ display_text();
+ }
+ break;
+
+ case XK_Right:
+ if (vtt->vol_loop > 0.0)
+ {
+ vtt->vol_loop-=0.01;
+ vtt->vol_scratch=1.0-vtt->vol_loop;
+ display_text();
+ }
+ break;
+#endif
+ }
+}
+
+/* tx_Window::handle_KeyRelease() : Evaluates xkeyev as KeyRelease Event */
+
+void tX_Window :: handle_KeyRelease()
+{
+ KeySym key;
+
+ key=XKeycodeToKeysym (disp, xkeyev->keycode, 0);
+
+ switch (key)
+ {
+ case XK_space:
+ {
+ vtt->speed=vtt->default_speed;
+ XUngrabPointer(disp, CurrentTime);
+ motor_on=1;
+ XAutoRepeatOn(disp);
+ }
+ break;
+ }
+}
+
+/* tx_Window::repaint() : Redraws all components of the window.*/
+
+void tX_Window :: repaint()
+{
+/*
+ No longer just clearing the window, as that produces
+ different results on different X-Servers, instead we paint
+ it black.
+*/
+ XSetForeground(disp, gc, black);
+ XFillRectangle(disp, win, gc, 0, 0, width, height);
+ display_data();
+ display_mode();
+ display_action();
+ display_text();
+}
+
+/* tx_Window::handle_Motion() : Evaluates xmotev as Motion Event */
+
+void tX_Window :: handle_Motion()
+{
+ int dist;
+ int nx;
+ f_prec tspeed;
+ Time ntime, dtime;
+
+ if (!playback_active) return;
+
+ nx=xmotev->x;
+ ntime=xmotev->time;
+
+ if (first_mot_event)
+ {
+ mx=nx;
+ mtime=ntime;
+ first_mot_event=0;
+ return;
+ }
+
+#ifdef USE_STOPSENSE
+ mouse_busy=sense_cycles;
+#endif
+
+ if ((ptrwarped) && (nx=medx))
+ {
+ mx=medx;
+ ptrwarped=0;
+ return;
+ }
+
+ if ((nx >= warpx_max) || (nx <= warpx_min))
+ {
+ XWarpPointer(disp, win, win, 0, 0, 0, 0, medx, medy);
+ ptrwarped=1;
+ }
+
+ if (motor_on) return;
+
+ dtime=ntime-mtime;
+ if (dtime==0) dtime=1;
+ dist=mx-nx;
+ tspeed= (f_prec) dist/dtime;
+ vtt->speed=tspeed*mouse_speed;
+
+ mx=nx;
+ mtime=ntime;
+}
+
+/* tx_Window::handle_event() : Evaluates the type of the event and calls
+ corresponding method.
+*/
+
+void tX_Window :: handle_event()
+{
+ switch (xev.type)
+ {
+ case KeyPress:
+ handle_KeyPress();
+ break;
+
+ case KeyRelease:
+ handle_KeyRelease();
+ break;
+
+ case MotionNotify:
+ handle_Motion();
+ break;
+
+ case Expose:
+ repaint();
+ break;
+
+ default:
+ printf("[tX:check_event] Unhandled Event of type: 0x%x\n", xev.type);
+ }
+}
+
+/* tx_Window::event_wait() : Waits for an event. Is called when playback
+ is not active.
+*/
+
+int tX_Window :: event_wait()
+{
+ XWindowEvent(disp, win, event_mask, &xev);
+ handle_event();
+ return(quit);
+}
+
+
+/* tX_Window::event_check() : Checks for an event. If there is one handle_event is called.
+ For use when playback is active.
+*/
+
+int tX_Window :: event_check()
+{
+#ifdef USE_STOPSENSE
+ mouse_busy--;
+ if ((mouse_busy==0) && (!motor_on)) vtt->speed=0.0;
+#endif
+ if (XCheckWindowEvent(disp, win, event_mask, &xev) == True)
+ {
+ handle_event();
+ }
+ return (quit);
+}
+
+/* tX_Window::loop() : Calls event_check and event_wait until
+ quit is set.
+*/
+
+void tX_Window :: loop()
+{
+ int newpb;
+
+ while (!quit)
+ {
+ if (playback_active)
+ {
+ event_check();
+ if (playback_active)
+ {
+ newpb=!vtt->block_action();
+ if (!newpb)
+ {
+ vtt->needle_up();
+ if (vtt->mode == MODE_RECORD_SCRATCH)
+ {
+ vtt->store_rec_pos();
+ }
+ playback_active=newpb;
+
+ set_pos(0);
+ display_action();
+ }
+ XUngrabPointer(disp, CurrentTime);
+ playback_active=newpb;
+ }
+ }
+ else
+ {
+ event_wait();
+ }
+ }
+}
+
+/* tX_Window::display_mode() : displays the current vtt mode in the lower
+ right edge of the window (empty and full circle & arrow)
+*/
+
+void tX_Window :: display_mode()
+{
+ int x,y,w,h;
+
+ x=modex;
+ y=modey;
+ w=bt_w;
+ h=bt_h;
+
+ if (vtt->mode == MODE_SCRATCH) XSetForeground(disp, gc, col_activebtn.pixel);
+ else XSetForeground(disp, gc, col_inactivebtn.pixel);
+
+ XDrawArc(disp, win, gc, x, y, w, h, 0, 23040);
+
+ x+=bt_a+bt_w;
+
+ if (vtt->mode == MODE_RECORD_SCRATCH) XSetForeground(disp, gc, col_activebtn.pixel);
+ else XSetForeground(disp, gc, col_inactivebtn.pixel);
+
+ XFillArc(disp, win, gc, x, y, w, h, 0, 23040);
+ XDrawArc(disp, win, gc, x, y, w, h, 0, 23040);
+
+ x+=bt_a+bt_w;
+
+ if (vtt->mode == MODE_PLAYBACK_RECORDED) XSetForeground(disp, gc, col_activebtn.pixel);
+ else XSetForeground(disp, gc, col_inactivebtn.pixel);
+
+ XDrawLine(disp, win, gc, x, y, x, y+bt_h);
+ XDrawLine(disp, win, gc, x, y, x+bt_w, y+(bt_h/2));
+ XDrawLine(disp, win, gc, x, y+bt_h, x+bt_w, y+(bt_h/2));
+
+ XSync(disp, False);
+}
+
+/* tX_Window :: display_action() : Displays the current playback status. */
+
+void tX_Window :: display_action()
+{
+ int x,y,w,h;
+
+ x=modex+3*(bt_w+bt_a);
+ y=modey;
+ w=2*bt_w+bt_a;
+ h=bt_h;
+
+
+ if (playback_active)
+ {
+ XSetForeground(disp, gc, col_pos.pixel);
+ XDrawRectangle(disp, win, gc, x, y, w, h);
+ XFillRectangle(disp, win, gc, x, y, w, h);
+ }
+ else
+ {
+ XSetForeground(disp, gc, black);
+ XFillRectangle(disp, win, gc, x, y, w, h);
+ XSetForeground(disp, gc, col_pos.pixel);
+ XDrawRectangle(disp, win, gc, x, y, w, h);
+ }
+}
+
+/* tX_Window::display_text() : The method name says it all...*/
+
+void tX_Window :: display_text()
+{
+ int x,y,w,h;
+ char buffer[256];
+ char out[1024];
+
+ x=0; y=height-TOOLBAR_SIZE; w=modex-1; h=TOOLBAR_SIZE;
+
+ XSetForeground(disp, gc, black);
+ XFillRectangle(disp, win, gc, x, y, w, h);
+
+ x=BORDER_ALIGN;
+ y=height-TOOLBAR_SIZE+2*BORDER_ALIGN;
+
+ strcpy(out, "Scratch: [");
+ strcat(out, s_name);
+ strcat(out, "] - ");
+
+ if (strlen(l_name))
+ {
+ strcat(out, "Loop: [");
+ strcat(out, l_name);
+ strcat(out, "] - ");
+ }
+
+ if (vtt->do_mix)
+ {
+#ifdef USE_OLD_MIX
+ strcat(out, "Mix: [ON]");
+#else
+ sprintf(buffer, "Mix: [S:%3i/L:%3i]", (int) (vtt->vol_scratch * 100), (int) (vtt->vol_loop * 100));
+ strcat(out, buffer);
+#endif
+ }
+ else strcat(out, "Mix: [OFF]");
+
+ if (strlen(vtt->last_fn))
+ {
+ sprintf (buffer, " - Saved: [%s] ", vtt->last_fn);
+ strcat(out, buffer);
+ }
+
+ XSetForeground(disp, gc, col_frame.pixel);
+ XDrawString(disp, win, gc, x, y, out, strlen(out));
+
+ XSync(disp, False);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: tX.h
+
+ Description: Header to tX.cc
+
+ For a closer description of the methods see implementation (tX.cc).
+*/
+
+#ifndef _H_TX
+#define _H_TX
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/shape.h>
+
+class tX_Window;
+class Virtual_TurnTable;
+
+#include "turntable.h"
+#include "tX_types.h"
+
+class tX_Window
+{
+ XColor col_data;
+ XColor col_frame;
+ XColor col_pos;
+ XColor col_activebtn;
+ XColor col_inactivebtn;
+ XColor col_marker;
+
+ Font font;
+
+ unsigned long black;
+ unsigned long white;
+
+ int verbose;
+
+ Display *disp;
+ Window win;
+ XSetWindowAttributes set_attr;
+ GC gc;
+ XGCValues xgcv;
+ long event_mask;
+ XEvent xev;
+ XKeyEvent *xkeyev;
+ XMotionEvent *xmotev;
+
+ int modex, modey, bt_w, bt_h, bt_a;
+
+ int samples_per_pixel;
+ int mouse_border;
+ f_prec mouse_speed;
+ int sense_cycles;
+ char s_name[256];
+ char l_name[256];
+
+ int width;
+ int height;
+ int medx;
+ int medy;
+ int warpx_max;
+ int warpx_min;
+
+ int data_disp_x;
+ int data_disp_y;
+
+ int data_disp_width;
+ int data_disp_height;
+
+ unsigned int data_samples;
+ int16_t *data_ptr;
+
+ int pos_y;
+ int pos_max_x;
+
+ int motor_on;
+ int first_mot_event;
+
+#ifdef USE_STOPSENSE
+ int mouse_busy;
+#endif
+
+ int y0;
+
+ int ptrwarped;
+
+ int quit;
+
+ Virtual_TurnTable *vtt;
+
+ int mx,my;
+ Time mtime;
+
+ public:
+ int playback_active;
+
+ tX_Window(Virtual_TurnTable *, int, int, int, int, f_prec, int, char *, char *);
+ ~tX_Window();
+
+ void prepare_data_display(int16_t *, unsigned int);
+ void display_data();
+ void display_mode();
+ void display_action();
+ void display_text();
+ void set_pos(int pos);
+ int get_samples_per_pixel();
+
+ int event_wait();
+ int event_check();
+ void handle_event();
+ void handle_KeyPress();
+ void handle_KeyRelease();
+ void handle_Motion();
+ void repaint();
+ void loop();
+};
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: tX_types.h
+
+ Description: Use correct type sizes. If <sys/types.h> is not
+ available define USE_X86_TYPES on i386 machines
+*/
+
+#ifndef _H_TX_TYPES
+#define _H_TX_TYPES
+
+#ifndef USE_X86_TYPES
+
+#include <sys/types.h>
+
+#else
+
+#define int8_t char
+#define int16_t short
+#define int32_t long
+
+#endif
+
+#endif
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: turntable.cc
+
+ Description: This implements the virtual turntable. Contains
+ all audio related stuff.
+
+ I no longer have -DUSE_ALIASING as I don´t have time to maintain the same
+ code twice. Aliasing is now default.
+
+ Changes:
+
+ 20 Mar 1999: Setting the buffer size in open_device() no
+ happens before the DSP_RESET. This might
+ help fighting latency with some audio drivers.
+
+ 20 Mar 1999: If KEEP_DEV_OPEN is defined the audio device
+ will be opened only once and is only closed
+ by termination of the terminatorX-process via
+ the OS. This helps if you have problems with
+ memory fragmentation and the sounddriver fails
+ to malloc the audiobuffers. If your sounddriver
+ causes awfull clicks on opening the device this
+ is nice too. Of course other processes can not access
+ the audio device while terminatorX is running.
+ see open_dev() and close_dev().
+
+ 20 Mar 1999: Big endian support
+
+ 20 Mar 1999: Removed audio clicks. Use -DHANDLE_STOP to re-enable.
+ This is not the solution I want as it produces
+ what I consider corrupt audio.
+
+ 21 Mar 1999: do_mix is enabled automatically now if mix_data is
+ available.
+
+ 23 Mar 1999: new mixing routine allows to set the loop to scratch
+ ratio. Old mixing (is faster) can be re-enabled
+ via -DUSE_OLD_MIX. I consider this code as obsolete
+ if nobody tells me he/she uses that switch I'll drop the
+ old code.
+*/
+
+#include "turntable.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/soundcard.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "wav_file.h"
+#include <math.h>
+
+#include "endian.h"
+#include "tX_types.h"
+
+/* Virtual_TurnTable::Virtual_TurnTable() : Does what a constructor does...
+ intialization.
+*/
+
+Virtual_TurnTable :: Virtual_TurnTable(TT_init *init_data)
+{
+#ifdef USE_CONSOLE
+ if (init_data->verbose) puts("[VTT] Initializing.");
+#endif
+
+#ifndef USE_OLD_MIX
+ vol_loop=0.5;
+ vol_scratch=0.5;
+#endif
+ speed=init_data->speed;
+ strcpy(devicename, init_data->devicename);
+
+ default_speed=init_data->default_speed;
+ buff_cfg=init_data->buff_cfg;
+
+ playback_data=init_data->playback_data;
+ playback_size=init_data->playback_size;
+
+ record_data=init_data->record_data;
+ record_size=init_data->record_size;
+
+ mix_data=init_data->mix_data;
+ mix_size=init_data->mix_size;
+
+ mix_pos=mix_data;
+ mix_max=mix_data+(size_t) (mix_size/sizeof(int16_t));
+
+ last_block_recorded=0;
+
+ verbose=init_data->verbose;
+
+ if (!mix_data) do_mix=0; else do_mix=1;
+
+ dev_open=0;
+ devicefd=0;
+ win=init_data->win;
+ last_sample=0;
+
+ strcpy(file_name, init_data->file_name);
+ file_ctr=0;
+
+ mode=MODE_SCRATCH;
+
+ store_pos=record_data;
+ strcpy(last_fn,"");
+}
+
+/* Virtual_TurnTable::open_dev() : Opens and configures the audio device */
+
+int Virtual_TurnTable :: open_dev()
+{
+#ifdef USE_CONSOLE
+ if (verbose) puts("[VTT:open_dev] Trying to open device.");
+#endif
+ int i=0;
+ int p;
+
+#ifdef KEEP_DEV_OPEN
+ if (dev_open) return(0);
+#else
+ if (dev_open)
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:open_dev] Error: Device already open.");
+#endif
+ return (1);
+ }
+#endif
+
+ devicefd = open(devicename, O_WRONLY, 0);
+
+ /* setting buffer size */
+
+ p=buff_cfg;
+
+ i = ioctl(devicefd, SNDCTL_DSP_SETFRAGMENT, &p);
+
+ ioctl(devicefd, SNDCTL_DSP_RESET, 0);
+
+ /* 16 Bits */
+
+ p = 16;
+ i += ioctl(devicefd, SOUND_PCM_WRITE_BITS, &p);
+
+ /* MONO */
+
+ p = 1;
+ i += ioctl(devicefd, SOUND_PCM_WRITE_CHANNELS, &p);
+
+ /* 44.1 khz */
+
+ p = 44100;
+ i += ioctl(devicefd, SOUND_PCM_WRITE_RATE, &p);
+
+ i += ioctl(devicefd, SNDCTL_DSP_GETBLKSIZE, &deviceblocksize);
+
+ ioctl(devicefd, SNDCTL_DSP_SYNC, 0);
+
+ dev_open=!i;
+
+ return(i);
+}
+
+/* Virtual_TurnTable::close_dev() : Closes audio device */
+
+int Virtual_TurnTable :: close_dev()
+{
+#ifdef KEEP_DEV_OPEN
+ return(ioctl(devicefd, SNDCTL_DSP_POST, 0));
+#else
+#ifdef USE_CONSOLE
+ if (verbose) puts("[VTT:close_dev] Trying to close device.");
+#endif
+ if (!dev_open)
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:close_dev] Error: Device not open.");
+#endif
+ return(1);
+ }
+
+ close(devicefd);
+ devicefd=0;
+ dev_open=0;
+
+ return(0);
+#endif
+}
+
+/* Virtual_TurnTable::set_window() : UGLY. Sets the win pointer of
+ Virutal_TurnTable. Required for position updates.
+*/
+
+void Virtual_TurnTable :: set_window(tX_Window *window)
+{
+ win=window;
+}
+
+/* Virtual_TurnTable::play_block() : plays the given audio buffer size must
+ be deviceblocksize.
+*/
+
+void Virtual_TurnTable :: play_block(int16_t *buffer)
+{
+#ifdef BIG_ENDIAN_MACHINE
+#ifndef BIG_ENDIAN_AUDIO
+ swapbuffer(buffer, samples_per_block);
+#endif
+#else
+#ifdef BIG_ENDIAN_AUDIO
+ swapbuffer(buffer, samples_per_block);
+#endif
+#endif
+ write(devicefd, buffer, deviceblocksize);
+}
+
+/* Virtual_TurnTable::render_block() : "renders" one block of audio (scratch)
+ data into given buffer (size == deviceblocksize)
+*/
+
+void Virtual_TurnTable :: render_block(int16_t *buffer)
+{
+ int16_t *ptr;
+
+ int sample;
+
+ int x_upd;
+
+ f_prec true_pos_a;
+
+ f_prec diff;
+ f_prec amount_a;
+ f_prec amount_b;
+
+ unsigned int real_pos_a;
+
+ f_prec sample_a;
+ f_prec sample_b;
+
+ f_prec sample_res;
+
+ if (win)
+ {
+ x_upd=(int) (pos/spp);
+ if (x_upd!=x_last)
+ {
+ win->set_pos(x_upd);
+ x_last=x_upd;
+ }
+ }
+
+ if (speed != target_speed)
+ {
+ target_speed=speed;
+ speed_step=target_speed-real_speed;
+ speed_step/=10.0;
+ }
+
+ if (target_speed != real_speed)
+ {
+ real_speed+=speed_step;
+ if ((speed_step<0) && (real_speed<target_speed)) real_speed=target_speed;
+ else
+ if ((speed_step>0) && (real_speed>target_speed)) real_speed=target_speed;
+ }
+
+ for (sample=0; sample < samples_per_block; sample++)
+ {
+#ifdef HANDLE_STOP
+ if (real_speed!=0)
+ {
+#endif
+ pos+=real_speed;
+ if (pos>maxpos) pos-=maxpos;
+ else if (pos<0) pos+=maxpos;
+
+ true_pos_a=floor(pos);
+
+ diff=pos-true_pos_a;
+
+ amount_b=diff;
+ amount_a=1.0-diff;
+
+ real_pos_a=(unsigned int) true_pos_a;
+
+ ptr=&playback_data[real_pos_a];
+ sample_a=(f_prec) *ptr;
+
+ if (real_pos_a == playback_size)
+ {
+ sample_b=*playback_data;
+ }
+ else
+ {
+ ptr++;
+ sample_b=(f_prec) *ptr;
+ }
+
+ sample_res=(sample_a*amount_a)+(sample_b*amount_b);
+#ifdef HANDLE_STOP
+ last_sample=(int16_t) sample_res;
+ buffer[sample]=last_sample;
+#else
+ buffer[sample]=(int16_t) sample_res;
+#endif
+#ifdef HANDLE_STOP
+ }
+ else
+ {
+ if (last_sample==1) last_sample=0;
+ if (last_sample!=0)
+ {
+ last_sample=(int16_t) (((f_prec) last_sample) * 0.9);
+ buffer[sample]=last_sample;
+ }
+ else
+ {
+ buffer[sample]=0;
+ }
+ }
+#endif
+ }
+}
+
+/* Virtual_TurnTable::needle_down() : Starts playback */
+
+void Virtual_TurnTable :: needle_down()
+{
+ int result;
+
+ spp=(f_prec) win->get_samples_per_pixel();
+ pos=0;
+ x_last=-1;
+ maxpos=(f_prec) playback_size / 2.0;
+
+ real_speed=speed;
+ target_speed=speed;
+ speed_step=0;
+/*
+#ifdef USE_CONSOLE
+ puts("[VTT:needle_down] Trying to open device.");
+#endif */
+ result = open_dev();
+
+ if (result)
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:needle_down] Error: Failed opening device. Fatal. Giving up.");
+#endif
+ exit(1);
+ }
+
+#ifdef USE_CONSOLE
+ if (verbose) printf("[VTT:needle_down] Using Blocksize of %i Bytes.\n", deviceblocksize);
+#endif
+ samples_per_block=deviceblocksize/sizeof(int16_t);
+
+ samplebuffer=(int16_t *) malloc(deviceblocksize);
+
+ if (!samplebuffer)
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:needle_down] Error. Failed to allocate sample_buffer. Fatal. Giving up.");
+#endif
+ exit(1);
+ }
+
+ store_pos=record_data;
+ mix_pos=mix_data;
+ block_ctr=0;
+ block_max=record_size/deviceblocksize;
+}
+
+/* Virtual_TurnTable::needle_up() : Stops playback. */
+
+void Virtual_TurnTable :: needle_up()
+{
+ int result;
+
+ free(samplebuffer);
+
+/*#ifdef USE_CONSOLE
+ puts("[VTT:needle_up] Trying to close device.");
+#endif */
+ result = close_dev();
+#ifdef USE_CONSOLE
+ if (result)
+ puts("[VTT:needle_up] Error: Failed closing device.");
+#endif
+
+}
+
+/* Virtual_TurnTable::set_speed() : Sets the rotation speed of the
+ Virtual TurnTable. Rarely used as writing to speed directly is
+ faster (and uglier).
+*/
+
+void Virtual_TurnTable :: set_speed(f_prec targetspeed)
+{
+#ifdef FUSE_CONSOLE
+ if (verbose) printf("[VTT:set_speed] Speed setup: %f.\n", targetspeed);
+#endif
+ speed=targetspeed;
+}
+
+/* Virtual_TurnTable::set_mode() : Just what it says ..*/
+
+void Virtual_TurnTable :: set_mode(int newmode)
+{
+ mode=newmode;
+}
+
+/* Virtual_TurnTable::get_next_storage_block() : Returns a pointer to the next
+ block in recordbuffer.
+*/
+
+int16_t * Virtual_TurnTable :: get_next_storage_block()
+{
+ if (block_ctr)
+ {
+ block_ctr++;
+ if (block_ctr > block_max) return(NULL);
+ store_pos+=(size_t) samples_per_block;
+ return(store_pos);
+ }
+ else
+ {
+ block_ctr++;
+ return(store_pos);
+ }
+
+}
+
+/* Virtual_TurnTable::() : This triggers all required actions depending
+ on current mode.
+*/
+
+int Virtual_TurnTable :: block_action()
+{
+ int16_t *ptr;
+
+ switch(mode)
+ {
+ case MODE_SCRATCH:
+ render_block(samplebuffer);
+ if (do_mix) add_mix(samplebuffer);
+ play_block(samplebuffer);
+ return(0);
+
+ case MODE_RECORD_SCRATCH:
+ ptr=get_next_storage_block();
+ if (ptr)
+ {
+ render_block(ptr);
+ if (do_mix)
+ {
+ memcpy(samplebuffer, ptr, deviceblocksize);
+ add_mix(samplebuffer);
+ play_block(samplebuffer);
+ }
+ else
+ {
+ play_block(ptr);
+ }
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+
+ case MODE_PLAYBACK_RECORDED:
+ if (block_ctr>last_block_recorded) return (1);
+ ptr=get_next_storage_block();
+ if (ptr)
+ {
+ if (do_mix)
+ {
+ memcpy(samplebuffer, ptr, deviceblocksize);
+ add_mix(samplebuffer);
+ play_block(samplebuffer);
+ }
+ else
+ {
+ play_block(ptr);
+ }
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+ }
+ return(1);
+}
+
+/* Virtual_TurnTable::add_mix() : This mixes the loop file date to the
+ given buffer (size = deviceblocksize)
+*/
+
+void Virtual_TurnTable :: add_mix(int16_t * buffer)
+{
+ int sample;
+ int16_t *scratch_pos;
+
+#ifdef USE_OLD_MIX
+ int16_t value;
+#else
+ f_prec f_val_s, f_val_l;
+#endif
+
+ for (sample=0, scratch_pos=buffer; sample < samples_per_block; sample ++, scratch_pos++)
+ {
+#ifdef USE_OLD_MIX
+ value=(*mix_pos)>>1;
+ value+=(*scratch_pos)>>1;
+ *scratch_pos=value;
+#else
+ f_val_l=(f_prec) *mix_pos;
+ f_val_l*=vol_loop;
+ f_val_s=(f_prec) *scratch_pos;
+ f_val_s*=vol_scratch;
+ *scratch_pos=(int16_t) (f_val_s + f_val_l);
+#endif
+ mix_pos++;
+ if (mix_pos>=mix_max) mix_pos=mix_data;
+ }
+}
+
+/* Virtual_TurnTable::toggle_mix() : Dis- or enable mixing of loop data.*/
+
+void Virtual_TurnTable :: toggle_mix()
+{
+ if (mix_data) do_mix=!do_mix;
+ else
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:toggle_mix] Error: Can't enable mixing: no loop loaded.");
+#endif
+ do_mix=0;
+ }
+}
+
+/* Virtual_TurnTable::store_rec_pos() : Stores current recording position
+ for later playback or saving.
+*/
+
+void Virtual_TurnTable :: store_rec_pos()
+{
+ if (block_ctr > block_max) last_block_recorded=block_max;
+ else last_block_recorded=block_ctr;
+}
+
+/* Virtual_TurnTable::() : See above and guess ;) */
+
+void Virtual_TurnTable :: reset_rec_pos()
+{
+ last_block_recorded=0;
+}
+
+/* Virtual_TurnTable::save() : Saves a recorded scratch. If the mix == 1
+ then with loop data mixed else unmixed raw scratch.
+*/
+
+void Virtual_TurnTable :: save(int mix)
+{
+ wav_sig out_wav;
+ int16_t *ptr;
+
+ if ((mix) && (!mix_data))
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:save] Error: Can't save a mixed file: no loop loaded.");
+#endif
+ return;
+ }
+
+ file_ctr++;
+
+ out_wav.srate=44100;
+ out_wav.chans=1;
+ out_wav.depth=16;
+ out_wav.bps=88200;
+ out_wav.blkalign=2;
+ out_wav.len=last_block_recorded*deviceblocksize;
+ out_wav.sofar=out_wav.len;
+
+ sprintf(out_wav.name, "%s%02i.wav", file_name, file_ctr);
+ strcpy(last_fn, out_wav.name);
+
+#ifdef USE_CONSOLE
+ if (!mix)
+ {
+ printf("[VTT:save] Saving RAW recorded scratch to %s.\n", out_wav.name);
+ }
+ else
+ {
+ printf("[VTT:save] Saving MIXED recorded scratch to %s.\n", out_wav.name);
+ }
+#endif
+
+ if (!open_wav_rec(&out_wav))
+ {
+#ifdef USE_CONSOLE
+ puts("[VTT:save] Failed to open output file.");
+#endif
+ return;
+ }
+
+ block_ctr=0;
+ store_pos=record_data;
+ mix_pos=mix_data;
+
+#ifndef BIG_ENDIAN_MACHINE
+ if (mix)
+#endif
+ samplebuffer=(int16_t *) malloc(deviceblocksize);
+
+ while (block_ctr<last_block_recorded)
+ {
+ ptr=get_next_storage_block();
+ if (mix)
+ {
+ memcpy(samplebuffer, ptr, deviceblocksize);
+ add_mix(samplebuffer);
+#ifdef BIG_ENDIAN_MACHINE
+ swapbuffer(samplebuffer, samples_per_block);
+#endif
+ write(out_wav.handle, samplebuffer, deviceblocksize);
+ }
+ else
+ {
+#ifdef BIG_ENDIAN_MACHINE
+ memcpy(samplebuffer, ptr, deviceblocksize);
+ swapbuffer(samplebuffer, samples_per_block);
+ write(out_wav.handle, samplebuffer, deviceblocksize);
+#else
+ write(out_wav.handle, ptr, deviceblocksize);
+
+#endif
+ }
+ }
+
+#ifndef BIG_ENDIAN_MACHINE
+ if (mix)
+#endif
+ free(samplebuffer);
+
+ close(out_wav.handle);
+
+#ifdef USE_CONSOLE
+ if (verbose) puts("[VTT:save] Saving done.");
+#endif
+}
+
+
+
+
+
+
+
--- /dev/null
+/*
+ terminatorX - realtime audio scratching software
+ Copyright (C) 1999 Alexander König
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ File: turntable.h
+
+ Description: Header to turntable.cc
+
+ For a closer desciption of the methods see implementation (tunrtable.cc).
+
+ Changes:
+
+ 20 Mar 1999: Using int16_t instead of short
+*/
+
+
+#ifndef _H_TURNTABLE
+#define _H_TURNTABLE
+
+#define MODE_SCRATCH 1
+#define MODE_RECORD_SCRATCH 2
+#define MODE_PLAYBACK_RECORDED 3
+
+#define f_prec double
+
+#include "tX.h"
+#include "tX_types.h"
+
+typedef struct {
+ f_prec speed;
+ f_prec default_speed;
+ int buff_cfg;
+ int bsize;
+ int16_t *playback_data;
+ unsigned int playback_size;
+ int16_t *record_data;
+ unsigned int record_size;
+ int16_t *mix_data;
+ unsigned int mix_size;
+ char devicename[256];
+ char file_name[128];
+ int verbose;
+ tX_Window *win;
+} TT_init;
+
+class Virtual_TurnTable
+{
+
+ f_prec real_speed;
+ f_prec target_speed;
+ f_prec speed_step;
+
+ f_prec pos;
+ f_prec maxpos;
+
+ int buff_cfg;
+
+ int x_last;
+ f_prec spp;
+
+ int samples_per_block;
+
+ int16_t last_sample;
+ int block_ctr;
+ int block_max;
+ int last_block_recorded;
+ int verbose;
+
+
+ public:
+
+#ifndef USE_OLD_MIX
+ f_prec vol_loop;
+ f_prec vol_scratch;
+#endif
+
+ /* Rotation-Speed of Turntable */
+ f_prec speed;
+ f_prec default_speed;
+
+ char devicename[256];
+ int devicefd;
+ int deviceblocksize;
+
+ tX_Window *win;
+
+ int file_ctr;
+ char file_name[128];
+ char last_fn[128];
+
+ int16_t *playback_data;
+ unsigned int playback_size;
+
+ int16_t *record_data;
+ int16_t *store_pos;
+ unsigned int record_size;
+
+ int16_t *mix_data;
+ unsigned int mix_size;
+ int16_t *mix_pos;
+ int16_t *mix_max;
+ int do_mix;
+
+ /* Dynamic Data */
+
+ int dev_open;
+ int mode;
+
+ public:
+
+ int16_t *samplebuffer;
+
+ Virtual_TurnTable(TT_init *);
+ ~Virtual_TurnTable();
+
+ void set_window(tX_Window *);
+
+ void needle_up();
+ void needle_down();
+
+ void play_block(int16_t *);
+ int16_t * get_next_storage_block();
+
+ void render_block(int16_t *);
+
+ void toggle_mix();
+ void set_mode(int );
+ void add_mix(int16_t *);
+
+ void store_rec_pos();
+ void reset_rec_pos();
+
+ void save(int);
+
+ int block_action();
+
+ void set_speed(f_prec);
+
+ int open_dev();
+ int close_dev();
+};
+
+#endif
--- /dev/null
+#ifndef _H_VERSION
+#define _H_VERSION
+
+#define VERSIONSTRING "terminatorX V2.3"
+
+#endif
--- /dev/null
+/*
+ wav_file.h - taken from wav-tools 1.1
+ Copyright (C) by Colin Ligertwood
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Changes:
+
+ 11 Mar 1999: -added license hint
+ -slight changes for use with terminatorX
+
+ 20 Mar 1999: now includes sys/types.h and uses types
+ defined there for interplatform compability.
+*/
+
+#ifndef _H_WAVFILE
+#define _H_WAVFILE
+
+#include "tX_types.h"
+
+typedef struct{
+ int32_t srate;
+ int8_t chans;
+ int8_t depth;
+ int32_t bps;
+ int8_t blkalign;
+ int32_t len;
+ int32_t sofar;
+
+ int handle;
+ char name[31];
+ char head[43];
+} wav_sig;
+
+extern int init_wav_read(char file_name[], wav_sig *info);
+extern int open_wav_rec(wav_sig *info);
+extern int rewrite_head(wav_sig *info);
+
+#endif
--- /dev/null
+/*
+ wav_read.cc - taken from wav-tools 1.1
+ Copyright (C) by Colin Ligertwood
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Changes:
+
+ 11 Mar 1999: added license hint
+
+ 20 Mar 1999: using types in sys/types for interplatform
+ compability.
+
+ 20 Mar 1999: support for big endian machines
+*/
+
+/* operations for verifying and reading wav files. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "wav_file.h"
+#include <unistd.h>
+
+#include "endian.h"
+
+/* Read little endian 16bit values little endian
+*/
+#define le_read16(x); \
+ int16_t tmp; \
+ int8_t *p; \
+ \
+ p = (int8_t *) &tmp; \
+ p[0] = info->head[x]; \
+ p[1] = info->head[x+1];
+
+
+/* Handle Endianess
+*/
+#ifdef BIG_ENDIAN_MACHINE
+#define read16(x); le_read16(x); swap16(&tmp); return(tmp);
+#else
+#define read16(x); le_read16(x); return(tmp);
+#endif
+
+/* Read little endian 32bit values little endian
+*/
+#define le_read32(x); \
+ int32_t tmp; \
+ int8_t *p; \
+ \
+ p = (int8_t *) &tmp; \
+ p[0] = info->head[x]; \
+ p[1] = info->head[x+1]; \
+ p[2] = info->head[x+2]; \
+ p[3] = info->head[x+3];
+
+
+/* Handle Endianess
+*/
+#ifdef BIG_ENDIAN_MACHINE
+#define read32(x); le_read32(x); swap32(&tmp); return(tmp);
+#else
+#define read32(x); le_read32(x); return(tmp);
+#endif
+
+ /* wav header is 44 bytes long */
+int open_wav(char *header, char file_name[]){
+ int handle;
+ handle = open(file_name, O_RDONLY, S_IREAD);
+ read(handle,(char *) header, 44);
+
+ return(handle);
+}
+
+int16_t get_wav_format(wav_sig *info){
+ read16(20);
+}
+
+ /* mono or stereo */
+int8_t get_wav_channels(wav_sig *info){
+ return(info->head[22]);
+// read16(22);
+}
+
+ /* sample rate */
+int32_t get_wav_srate(wav_sig *info){
+ read32(24);
+}
+
+int32_t get_wav_bps(wav_sig *info){
+ read32(28);
+}
+
+int8_t get_wav_blkalign(wav_sig *info){
+ return(info->head[32]);
+// read16(32);
+}
+
+ /* sample depth (8bit or 16bit) */
+int8_t get_wav_depth(wav_sig *info){
+ return(info->head[34]);
+// read16(34);
+}
+
+ /* data section only == totalfile - 44 */
+int32_t get_wav_len(wav_sig *info){
+ read32(40);
+}
+
+
+int init_wav_read(char file_name[], wav_sig *info){
+ info->handle = open_wav(info->head, file_name);
+ strcpy(info->name,file_name);
+ info->chans = get_wav_channels(info);
+ info->srate = get_wav_srate(info);
+ info->bps = get_wav_bps(info);
+ info->blkalign = get_wav_blkalign(info);
+ info->depth = get_wav_depth(info);
+ info->len = get_wav_len(info);
+ return(info->handle);
+}
--- /dev/null
+/*
+ wav_write.cc - taken from wav-tools 1.1
+ Copyright (C) by Colin Ligertwood
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Changes:
+
+ 11 Mar 1999: -added license hint
+ -added return statement in rewrite_head
+
+ 20 Mar 1999: -using sys/types.h for type sizes for interplatform
+ compatibility
+
+ 22 Mar 1999: removed some wav-tools bugs (handling 8-Bit
+ values as 16Bit integers)
+*/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/soundcard.h>
+#include "wav_file.h"
+#include <unistd.h>
+
+#include "endian.h"
+
+void init_head(wav_sig *info){
+ int16_t tmp16;
+ int32_t tmp32;
+
+ strcpy(info->head, "RIFF WAVEfmt data ");
+
+ tmp32=(info->sofar + 32);
+#ifdef BIG_ENDIAN_MACHINE
+ swap32(&tmp32);
+#endif
+ *(int32_t *)&info->head[4] = tmp32;
+
+
+ tmp32=16;
+#ifdef BIG_ENDIAN_MACHINE
+ swap32(&tmp32);
+#endif
+ *(int32_t *)&info->head[16] = tmp32;
+
+ tmp16=1;
+#ifdef BIG_ENDIAN_MACHINE
+ swap16(&tmp16);
+#endif
+ *(int16_t *)&info->head[20] = tmp16;
+
+ info->head[22] = info->chans;
+ info->head[23] = 0;
+
+ tmp32=info->srate;
+#ifdef BIG_ENDIAN_MACHINE
+ swap32(&tmp32);
+#endif
+ *(int32_t *)&info->head[24] = tmp32;
+
+ tmp32=info->bps;
+#ifdef BIG_ENDIAN_MACHINE
+ swap32(&tmp32);
+#endif
+ *(int32_t *)&info->head[28] = tmp32;
+
+ info->head[32] = info->blkalign;
+ info->head[33] = 0;
+
+ info->head[34] = info->depth;
+ info->head[35] = 0;
+
+ tmp32=info->sofar;
+#ifdef BIG_ENDIAN_MACHINE
+ swap32(&tmp32);
+#endif
+ *(int32_t *)&info->head[40] = tmp32;
+}
+
+int open_wav_rec(wav_sig *info){
+ info->handle = open(info->name, O_CREAT | O_RDWR, 0644);
+ init_head(info);
+ write(info->handle, info->head, 44);
+ return(info->handle);
+}
+
+int rewrite_head(wav_sig *info){
+ lseek(info->handle, 0, SEEK_SET);
+ init_head(info);
+ write(info->handle, info->head, 44);
+ /* make -Wall shut_up */
+ return(0);
+}