From c948feeef3c2356fb9f865459b0e13c7e169fc38 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 14 2020 11:55:47 +0000 Subject: libgdither-0.6 base --- diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..bf50f20 --- /dev/null +++ b/COPYING @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307 USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d2793d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +VERSION = 0.6 +PREFIX = /usr/local +CFLAGS = -Wall -g -I. -O3 -funroll-loops -finline-limit=9999999 -ffast-math -malign-double -march=`uname -m` -fPIC + +TARDIR = libgdither-$(VERSION) + +all: libgdither.so + +gdither.o: gdither.c gdither.h gdither_types_internal.h + $(CC) $(CFLAGS) -c gdither.c + +libgdither.so: gdither.o + $(CC) -shared gdither.o -o libgdither.so + +libgdither.pc: libgdither.pc.in Makefile + sed -e 's|@VERSION@|$(VERSION)|' -e 's|@PREFIX@|$(PREFIX)|' \ + libgdither.pc.in > libgdither.pc + +install: all + install -d $(PREFIX)/lib/ + install libgdither.so $(PREFIX)/lib/ + install -d $(PREFIX)/include/ + install gdither.h $(PREFIX)/include/ + install gdither_types.h $(PREFIX)/include/ + install -d $(PREFIX)/lib/pkgconfig/ + install libgdither.pc $(PREFIX)/lib/pkgconfig/ + +clean: + rm -f *.o *.so + (cd tests && make clean) + (cd examples && make clean) + +dist: all libgdither.pc + rm -rf $(TARDIR) + mkdir -p $(TARDIR)/tests $(TARDIR)/examples + cp README COPYING Makefile *.c *.h libgdither.pc \ + $(TARDIR) + cp tests/Makefile tests/*.[ch] tests/*.cc \ + $(TARDIR)/tests/ + cp examples/Makefile examples/*.[ch] \ + $(TARDIR)/examples/ + (cd $(TARDIR) && make test clean) + tar cfz $(TARDIR).tar.gz $(TARDIR) + @rm -rf $(TARDIR) + +test: all + (cd tests && make test) diff --git a/README b/README new file mode 100644 index 0000000..b29828a --- /dev/null +++ b/README @@ -0,0 +1,24 @@ +libgdither: a library for applying dithering to PCM audio sources. + +This code is (c) Steve Harris 2001-2004 and released under the GNU Public +Licence. Details may be found in the file COPYING. + +http://plugin.org.uk/libgdither/ + + +Libgdither is a GPL'd library library for performing audio dithering on +PCM samples. The dithering process should be carried out before reducing +the bit width of PCM audio data (eg. float to 16 bit int conversions) to +preserve audio quality. + +It can do conversions between any combination of: + +in out (optionally interleaved) +------------------------------------------------------------- +normalised mono float 8bit unsigned ints +normalised mono double 16bit signed ints + 32bit signed ints + normalised float + normalised double + +At any bitdepth supported by the input and output formats diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..2a95bd7 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,12 @@ +CFLAGS = -I.. -O3 -g -Wall --std=c99 +LDFLAGS = ../gdither.o -lm + +PROGS = ex1 + +all: $(PROGS) ../gdither.o + +../gdither.o: ../gdither.c + (cd .. && make) + +clean: + rm -f $(PROGS) *.o diff --git a/examples/ex1.c b/examples/ex1.c new file mode 100644 index 0000000..7ced3c7 --- /dev/null +++ b/examples/ex1.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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. + * + * $Id: ex1.c $ + */ + +#include +#include +#include + +#define SIZE 256 + +#include "gdither.h" + +int main(int argc, char *argv[]) +{ + GDither ds; + float in[SIZE]; /* test input data */ + double ind[SIZE]; /* test input data */ + int32_t out32[SIZE]; /* test output data: 1 chan 32bit */ + int16_t out16[SIZE][4]; /* test output data: 4 chan 16bit */ + float outf[SIZE]; /* test output data: 1 chan float */ + int i; + + /* --- Example 1a --- */ + + /* create an arbitrary sinewave for testing */ + for (i=0; i + * + * 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. + * + * $Id: dither.cc,v 1.3 2004/02/22 23:04:00 taybin Exp $ + */ + +#include "gdither_types_internal.h" +#include "gdither.h" +#include "noise.h" + +/* this monstrosity is necessary to get access to lrintf() and random(). + whoever is writing the glibc headers and should be + hauled off to a programmer re-education camp. for the rest of + their natural lives. or longer. +*/ + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 +#ifdef __cplusplus +#include +#else +#include +#endif + +#undef __USE_SVID +#define __USE_SVID 1 +#ifdef __cplusplus +#include +#else +#include +#endif + +/* and even then sometimes it doesn't work... */ +long lrintf(float); + +#include + +/* Lipshitz's minimally audible FIR, only really works for 46kHz-ish signals */ +static const float shaped_bs[] = { 2.033f, -2.165f, 1.959f, -1.590f, 0.6149f }; +// 2nd order: static const float shaped_bs[] = { 1.652f, -1.049, 0.1382 }; + +/* Some useful constants */ +#define MAX_U8 255 +#define MIN_U8 0 +#define SCALE_U8 128.0f + +#define MAX_S16 32767 +#define MIN_S16 -32768 +#define SCALE_S16 32768.0f + +#define MAX_S24 8388607 +#define MIN_S24 -8388608 +#define SCALE_S24 8388608.0f + +GDither gdither_new(GDitherType type, unsigned int channels, + GDitherSize bit_depth, int dither_depth) +{ + GDither s; + + s = (GDither)calloc(1, sizeof(struct GDither_s)); + s->type = type; + s->channels = channels; + s->bit_depth = (int)bit_depth; + + if (dither_depth <= 0 || dither_depth > (int)bit_depth) { + dither_depth = (int)bit_depth; + } + s->dither_depth = dither_depth; + + s->scale = (float)(1LL << (dither_depth - 1)); + if (bit_depth == GDitherFloat || bit_depth == GDitherDouble) { + s->post_scale_fp = 1.0f / s->scale; + s->post_scale = 0; + } else { + s->post_scale_fp = 0.0f; + s->post_scale = 1 << ((int)bit_depth - dither_depth); + } + + switch (bit_depth) { + case GDither8bit: + /* Unsigned 8 bit */ + s->bias = 1.0f; + s->clamp_u = 255; + s->clamp_l = 0; + break; + case GDither16bit: + /* Signed 16 bit */ + s->bias = 0.0f; + s->clamp_u = 32767; + s->clamp_l = -32768; + break; + case GDither32bit: + /* Signed 24 bit, in upper 24 bits of 32 bit word */ + s->bias = 0.0f; + s->clamp_u = 8388607; + s->clamp_l = -8388608; + break; + case GDitherFloat: + /* normalised float */ + s->bias = 0.0f; + s->clamp_u = lrintf(s->scale); + s->clamp_l = lrintf(-s->scale); + break; + case GDitherDouble: + /* normalised float */ + s->bias = 0.0f; + s->clamp_u = lrintf(s->scale); + s->clamp_l = lrintf(-s->scale); + break; + case 23: + /* special performance test case */ + s->scale = SCALE_S24; + s->post_scale = 256; + s->bias = 0.0f; + s->clamp_u = 8388607; + s->clamp_l = -8388608; + break; + default: + /* Not a bit depth we can handle */ + free(s); + + return NULL; + break; + } + + switch (type) { + case GDitherNone: + case GDitherRect: + /* No state */ + break; + + case GDitherTri: + /* The last whitenoise sample */ + s->tri_state = (float *) calloc(channels, sizeof(float)); + break; + + case GDitherShaped: + /* The error from the last few samples encoded */ + s->shaped_state = (GDitherShapedState*) + calloc(channels, sizeof(GDitherShapedState)); + break; + } + + return s; +} + +void gdither_free(GDither s) +{ + if (s) { + free(s->tri_state); + free(s->shaped_state); + free(s); + } +} + +inline static void gdither_innner_loop(const GDitherType dt, + const unsigned int stride, const float bias, const float scale, + const unsigned int post_scale, const int bit_depth, + const unsigned int channel, const unsigned int length, float *ts, + GDitherShapedState *ss, float *x, void *y, const int clamp_u, + const int clamp_l) +{ + unsigned int pos, i; + u_int8_t *o8 = (u_int8_t*) y; + int16_t *o16 = (int16_t*) y; + int32_t *o32 = (int32_t*) y; + float tmp, r, ideal; + int64_t clamped; + + i = channel; + for (pos = 0; pos < length; pos++, i += stride) { + tmp = x[pos] * scale + bias; + + switch (dt) { + case GDitherNone: + break; + case GDitherRect: + tmp -= GDITHER_NOISE; + break; + case GDitherTri: + r = GDITHER_NOISE - 0.5f; + tmp -= r - ts[channel]; + ts[channel] = r; + break; + case GDitherShaped: + /* Save raw value for error calculations */ + ideal = tmp; + + /* Run FIR and add white noise */ + ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f; + tmp += ss->buffer[ss->phase] * shaped_bs[0] + + ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK] + * shaped_bs[1] + + ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK] + * shaped_bs[2] + + ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK] + * shaped_bs[3] + + ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK] + * shaped_bs[4]; + + /* Roll buffer and store last error */ + ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK; + ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal; + break; + } + + clamped = lrintf(tmp); + if (clamped > clamp_u) { + clamped = clamp_u; + } else if (clamped < clamp_l) { + clamped = clamp_l; + } + + switch (bit_depth) { + case GDither8bit: + o8[i] = (u_int8_t) (clamped * post_scale); + break; + case GDither16bit: + o16[i] = (int16_t) (clamped * post_scale); + break; + case GDither32bit: + o32[i] = (int32_t) (clamped * post_scale); + break; + } + } +} + +/* floating pint version of the inner loop function */ +inline static void gdither_innner_loop_fp(const GDitherType dt, + const unsigned int stride, const float bias, const float scale, + const float post_scale, const int bit_depth, + const unsigned int channel, const unsigned int length, float *ts, + GDitherShapedState *ss, float *x, void *y, const int clamp_u, + const int clamp_l) +{ + unsigned int pos, i; + float *oflt = (float*) y; + double *odbl = (double*) y; + float tmp, r, ideal; + double clamped; + + i = channel; + for (pos = 0; pos < length; pos++, i += stride) { + tmp = x[i] * scale + bias; + + switch (dt) { + case GDitherNone: + break; + case GDitherRect: + tmp -= GDITHER_NOISE; + break; + case GDitherTri: + r = GDITHER_NOISE - 0.5f; + tmp -= r - ts[channel]; + ts[channel] = r; + break; + case GDitherShaped: + /* Save raw value for error calculations */ + ideal = tmp; + + /* Run FIR and add white noise */ + ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f; + tmp += ss->buffer[ss->phase] * shaped_bs[0] + + ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK] + * shaped_bs[1] + + ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK] + * shaped_bs[2] + + ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK] + * shaped_bs[3] + + ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK] + * shaped_bs[4]; + + /* Roll buffer and store last error */ + ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK; + ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal; + break; + } + + clamped = rintf(tmp); + if (clamped > clamp_u) { + clamped = clamp_u; + } else if (clamped < clamp_l) { + clamped = clamp_l; + } + + switch (bit_depth) { + case GDitherFloat: + oflt[i] = (float) (clamped * post_scale); + break; + case GDitherDouble: + odbl[i] = (double) (clamped * post_scale); + break; + } + } +} + +#define GDITHER_CONV_BLOCK 512 + +void gdither_run(GDither s, unsigned int channel, unsigned int length, + double *x, void *y) +{ + float conv[GDITHER_CONV_BLOCK]; + unsigned int i, pos; + char *ycast = (char *)y; + int step; + + switch (s->bit_depth) { + case GDither8bit: + step = 1; + break; + case GDither16bit: + step = 2; + break; + case GDither32bit: + case GDitherFloat: + step = 4; + break; + case GDitherDouble: + step = 8; + break; + default: + step = 0; + break; + } + + pos = 0; + while (pos < length) { + for (i=0; (i + pos) < length && i < GDITHER_CONV_BLOCK; i++) { + conv[i] = x[pos + i]; + } + gdither_runf(s, channel, i, conv, ycast + s->channels * step); + pos += i; + } +} + +void gdither_runf(GDither s, unsigned int channel, unsigned int length, + float *x, void *y) +{ + unsigned int pos, i; + float tmp; + int64_t clamped; + GDitherShapedState *ss = NULL; + + if (!s || channel >= s->channels) { + return; + } + + if (s->shaped_state) { + ss = s->shaped_state + channel; + } + + if (s->type == GDitherNone && s->bit_depth == 23) { + int32_t *o32 = (int32_t*) y; + + for (pos = 0; pos < length; pos++) { + i = channel + (pos * s->channels); + tmp = x[i] * 8388608.0f; + + clamped = lrintf(tmp); + if (clamped > 8388607) { + clamped = 8388607; + } else if (clamped < -8388608) { + clamped = -8388608; + } + + o32[i] = (int32_t) (clamped * 256); + } + + return; + } + + /* some common case handling code - looks a bit wierd, but it allows + * the compiler to optiomise out the branches in the inner loop */ + if (s->bit_depth == 8 && s->dither_depth == 8) { + switch (s->type) { + case GDitherNone: + gdither_innner_loop(GDitherNone, s->channels, 128.0f, SCALE_U8, + 1, 8, channel, length, NULL, NULL, x, y, + MAX_U8, MIN_U8); + break; + case GDitherRect: + gdither_innner_loop(GDitherRect, s->channels, 128.0f, SCALE_U8, + 1, 8, channel, length, NULL, NULL, x, y, + MAX_U8, MIN_U8); + break; + case GDitherTri: + gdither_innner_loop(GDitherTri, s->channels, 128.0f, SCALE_U8, + 1, 8, channel, length, s->tri_state, + NULL, x, y, MAX_U8, MIN_U8); + break; + case GDitherShaped: + gdither_innner_loop(GDitherShaped, s->channels, 128.0f, SCALE_U8, + 1, 8, channel, length, NULL, + ss, x, y, MAX_U8, MIN_U8); + break; + } + } else if (s->bit_depth == 16 && s->dither_depth == 16) { + switch (s->type) { + case GDitherNone: + gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S16, + 1, 16, channel, length, NULL, NULL, x, y, + MAX_S16, MIN_S16); + break; + case GDitherRect: + gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S16, + 1, 16, channel, length, NULL, NULL, x, y, + MAX_S16, MIN_S16); + break; + case GDitherTri: + gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S16, + 1, 16, channel, length, s->tri_state, + NULL, x, y, MAX_S16, MIN_S16); + break; + case GDitherShaped: + gdither_innner_loop(GDitherShaped, s->channels, 0.0f, + SCALE_S16, 1, 16, channel, length, NULL, + ss, x, y, MAX_S16, MIN_S16); + break; + } + } else if (s->bit_depth == 32 && s->dither_depth == 24) { + switch (s->type) { + case GDitherNone: + gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S24, + 256, 32, channel, length, NULL, NULL, x, + y, MAX_S24, MIN_S24); + break; + case GDitherRect: + gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S24, + 256, 32, channel, length, NULL, NULL, x, + y, MAX_S24, MIN_S24); + break; + case GDitherTri: + gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S24, + 256, 32, channel, length, s->tri_state, + NULL, x, y, MAX_S24, MIN_S24); + break; + case GDitherShaped: + gdither_innner_loop(GDitherShaped, s->channels, 0.0f, SCALE_S24, + 256, 32, channel, length, + NULL, ss, x, y, MAX_S24, MIN_S24); + break; + } + } else if (s->bit_depth == GDitherFloat || s->bit_depth == GDitherDouble) { + gdither_innner_loop_fp(s->type, s->channels, s->bias, s->scale, + s->post_scale_fp, s->bit_depth, channel, length, + s->tri_state, ss, x, y, s->clamp_u, s->clamp_l); + } else { + /* no special case handling, just process it from the struct */ + + gdither_innner_loop(s->type, s->channels, s->bias, s->scale, + s->post_scale, s->bit_depth, channel, + length, s->tri_state, ss, x, y, s->clamp_u, + s->clamp_l); + } +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/gdither.h b/gdither.h new file mode 100644 index 0000000..ca39b64 --- /dev/null +++ b/gdither.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2002 Steve Harris + * + * 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. + * + * $Id: dither.h,v 1.1 2003/01/07 16:44:16 pbd Exp $ + */ + +#ifndef GDITHER_H +#define GDITHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gdither_types.h" + +/* Create and initialise a state structure, takes a dither type, a number of + * channels and a bit depth as input + * + * The Dither type is one of + * + * GDitherNone - straight nearest neighbour rounding. Theres no pressing + * reason to do this at 8 or 16 bit, but you might want to at 24, for some + * reason. At the lest it will save you writing int->float conversion code, + * which is arder than it sounds. + * + * GDitherRect - mathematically most accurate, lowest noise floor, but not + * that good for audio. It is the fastest though. + * + * GDitherTri - a happy medium between Rectangular and Shaped, reasonable + * noise floor, not too obvious, quite fast. + * + * GDitherShaped - should have the least audible impact, but has the highest + * noise floor, fairly CPU intensive. Not advisible if your going to apply + * any frequency manipulation afterwards. + * + * channels, sets the number of channels in the output data, output data will + * be written interleaved into the area given to gdither_run(). Set to 1 + * if you are not working with interleaved buffers. + * + * bit depth, sets the bit width of the output sample data, it can be one of: + * + * GDither8bit - 8 bit unsiged + * GDither16bit - 16 bit signed + * GDither32bit - 24+bits in upper bits of a 32 bit word + * GDitherFloat - IEEE floating point (32bits) + * GDitherDouble - Double precision IEEE floating point (64bits) + * + * dither_depth, set the number of bits before the signal will be truncated to, + * eg. 16 will produce an output stream with 16bits-worth of signal. Setting to + * zero or greater than the width of the output format will dither to the + * maximum precision allowed by the output format. + */ +GDither gdither_new(GDitherType type, unsigned int channels, + GDitherSize bit_depth, int dither_depth); + +/* Frees memory used by gdither_new. + */ +void gdither_free(GDither s); + +/* Applies dithering to the supplied signal. + * + * channel is the channel number you are processing (0 - channles-1), length is + * the length of the input, in samples, x is the input samples (float), y is + * where the output samples will be written, it should have the approaprate + * type for the chosen bit depth + */ +void gdither_runf(GDither s, unsigned int channel, unsigned int length, + float *x, void *y); + +/* see gdither_runf, vut input argument is double format */ +void gdither_run(GDither s, unsigned int channel, unsigned int length, + double *x, void *y); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gdither_types.h b/gdither_types.h new file mode 100644 index 0000000..7eb0e4c --- /dev/null +++ b/gdither_types.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2002 Steve Harris + * + * 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. + * + * $Id: dither.h,v 1.1 2003/01/07 16:44:16 pbd Exp $ + */ + +#ifndef GDITHER_TYPES_H +#define GDITHER_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GDitherNone = 0, + GDitherRect, + GDitherTri, + GDitherShaped +} GDitherType; + +typedef enum { + GDither8bit = 8, + GDither16bit = 16, + GDither32bit = 32, + GDitherFloat = 25, + GDitherDouble = 54 +} GDitherSize; + +typedef void *GDither; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gdither_types_internal.h b/gdither_types_internal.h new file mode 100644 index 0000000..47f841e --- /dev/null +++ b/gdither_types_internal.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2002 Steve Harris + * + * 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. + * + * $Id: dither.h,v 1.1 2003/01/07 16:44:16 pbd Exp $ + */ + +#ifndef GDITHER_TYPES_H +#define GDITHER_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define GDITHER_SH_BUF_SIZE 8 +#define GDITHER_SH_BUF_MASK 7 + +/* this must agree with whats in gdither_types.h */ +typedef enum { + GDitherNone = 0, + GDitherRect, + GDitherTri, + GDitherShaped +} GDitherType; + +typedef enum { + GDither8bit = 8, + GDither16bit = 16, + GDither32bit = 32, + GDitherFloat = 25, + GDitherDouble = 54 +} GDitherSize; + +typedef struct { + unsigned int phase; + float buffer[GDITHER_SH_BUF_SIZE]; +} GDitherShapedState; + +typedef struct GDither_s { + GDitherType type; + unsigned int channels; + unsigned int bit_depth; + unsigned int dither_depth; + float scale; + unsigned int post_scale; + float post_scale_fp; + float bias; + int clamp_u; + int clamp_l; + float *tri_state; + GDitherShapedState *shaped_state; +} *GDither; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libgdither.pc b/libgdither.pc new file mode 100644 index 0000000..4aa7a01 --- /dev/null +++ b/libgdither.pc @@ -0,0 +1,9 @@ +prefix=/usr/local +libdir=/usr/local/lib +includedir=/usr/local/include + +Name: libgdither +Version: 0.6 +Description: A library for applying dithering to PCM audio sources +Libs: -L${libdir} -lgdither -lm +Cflags: -I${includedir} diff --git a/noise.h b/noise.h new file mode 100644 index 0000000..e5894b5 --- /dev/null +++ b/noise.h @@ -0,0 +1,21 @@ +#ifndef NOISE_H +#define NOISE_H + +/* Can be overrriden with any code that produces whitenoise between 0.0f and + * 1.0f, eg (random() / (float)RAND_MAX) should be a good source of noise, but + * its expensive */ +#ifndef GDITHER_NOISE +#define GDITHER_NOISE gdither_noise() +#endif + +#include + +inline static float gdither_noise() +{ + static uint32_t rnd = 23232323; + rnd = (rnd * 196314165) + 907633515; + + return rnd * 2.3283064365387e-10f; +} + +#endif diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..7e886b0 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,32 @@ +CFLAGS = -I.. -O3 -g -Wall -Werror --std=c99 +CPPFLAGS = -I.. -O3 -g -Wall -Werror +LDFLAGS = ../gdither.o -lm + +PROGS = runcheck distortion shapeplot noisetest interleavetest cplusplus +TESTPROGS = runcheck distortion noisetest interleavetest cplusplus + +all: $(PROGS) ../gdither.o + +test: all + @for i in $(TESTPROGS); do \ + ./$$i; \ + echo; \ + done; \ + +../gdither.o: ../gdither.c + (cd .. && make) + +distortion: distortion.c ../gdither.o + $(CC) $(CFLAGS) ../gdither.o -lm `pkg-config --libs fftw3` \ + distortion.c -o distortion + +shapeplot: shapeplot.c ../gdither.o + $(CC) $(CFLAGS) ../gdither.o -lm `pkg-config --libs fftw3` \ + shapeplot.c -o shapeplot + +noisetest: noisetest.c ../noise.h + $(CC) $(CFLAGS) -lm `pkg-config --libs fftw3` \ + noisetest.c -o noisetest + +clean: + rm -f $(PROGS) *.o diff --git a/tests/compare.h b/tests/compare.h new file mode 100644 index 0000000..e9e7188 --- /dev/null +++ b/tests/compare.h @@ -0,0 +1,197 @@ +int32_t compare[SIZE] = { + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -1717986816, -1288490240, -858993408, -429496832, 0, 429496832, + 858993408, 1288490240, 1717986816, 2147483392, 2147483392, + 2147483392, 2147483392, 2147483392, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -1717986816, + -1288490240, -858993408, -429496832, 0, 429496832, 858993408, + 1288490240, 1717986816, 2147483392, 2147483392, 2147483392, + 2147483392, 2147483392, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -1717986816, -1288490240, + -858993408, -429496832, 0, 429496832, 858993408, 1288490240, + 1717986816, 2147483392, 2147483392, 2147483392, 2147483392, + 2147483392, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -1717986816, -1288490240, -858993408, + -429496832, 0, 429496832, 858993408, 1288490240, 1717986816, + 2147483392, 2147483392, 2147483392, 2147483392, 2147483392, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -1717986816, -1288490240, -858993408, -429496832, 0, + 429496832, 858993408, 1288490240, 1717986816, 2147483392, + 2147483392, 2147483392, 2147483392, 2147483392, -2147483648, + -2147483648, -2147483648, -2147483648 +}; diff --git a/tests/cplusplus.cc b/tests/cplusplus.cc new file mode 100644 index 0000000..f44fce1 --- /dev/null +++ b/tests/cplusplus.cc @@ -0,0 +1,19 @@ +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + float data[1024]; + int16_t out[1024]; + + for (int i=0; i<1024; i++) { + data[i] = sin(i); + } + + GDither ds = gdither_new(GDitherNone, 1, GDither16bit, 0); + gdither_runf(ds, 0, 1024, data, out); + + return 0; +} diff --git a/tests/distortion.c b/tests/distortion.c new file mode 100644 index 0000000..bebca47 --- /dev/null +++ b/tests/distortion.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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. + * + * $Id: distortion-test.c $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gdither.h" + +#define SIZE 16384 + +#ifndef M_PI +#define M_PI 3.1415926 +#endif + +float in[SIZE]; +int32_t out[SIZE]; +double sin_tbl[SIZE]; +double sinless_tbl[SIZE]; + +void find_snr(GDitherType dt, const char *desc); +void find_res(GDitherType dt, const char *desc); + +int main(int argc, char *argv[]) +{ + int i; + + for (i=0; i harm_peak) harm_peak = amp[i]; + if (1 || amp[i] > -100.0) { + harm_sum += amp[i]; + harm_cnt++; + } + } else { + if (amp[i] > floor_peak) floor_peak = amp[i]; + floor_sum += amp[i]; + floor_cnt++; + } + + //sprintf(tmp, "%f\t%g\n", 48000.0 / (double)SIZE * (double)i, amp[i]); + //write(5, tmp, strlen(tmp)); + //printf("%d\t%g\n", i, amp_db); + } + printf("%s mean harmonic resonace = %.1fdB\n", desc, + harm_sum / harm_cnt - floor_sum / floor_cnt); + printf("%s peak harmonic resonance = %.1fdB\n", desc, + harm_peak - floor_peak); + if (dt != GDitherNone && harm_sum / harm_cnt - floor_sum / floor_cnt > 6.0) { + printf("excessive resonance peaks, failing\n"); + exit(1); + } + if (dt != GDitherNone && harm_peak - floor_peak > 6.0) { + printf("excessive resonance peaks, failing\n"); + exit(1); + } +} + +void find_snr(GDitherType dt, const char *desc) +{ + GDither *ds = gdither_new(dt, 1, GDither32bit, 24); + int i; + double sum_sq = 0.0; + double val; + + gdither_runf(ds, 0, SIZE, in, out); + for (i=0; i -141.0) { + printf("excessive noise, failed\n"); + exit(1); + } + break; + case GDitherTri: + if (val > -144.0) { + printf("excessive noise, failed\n"); + exit(1); + } + break; + case GDitherShaped: + if (val > -130.0) { + printf("excessive noise, failed\n"); + exit(1); + } + break; + } +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/tests/gettime.h b/tests/gettime.h new file mode 100644 index 0000000..0edabd2 --- /dev/null +++ b/tests/gettime.h @@ -0,0 +1,43 @@ +#ifndef GETTIME_H +#define GETTIME_H + +#include + + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + +#ifdef __i386__ +#define TIME(str, exp) { \ + long long _then, _now, best = 1000000000; \ + int i; \ + for (i=0; i<10; i++) { \ + rdtscll(_then); \ + exp; \ + rdtscll(_now); \ + if (_now - _then < best) { \ + best = _now - _then; \ + } \ + } \ + printf(str " took %.1f cycles/sample\n", (double)best/(double)SIZE); \ +} +#else +#define TIME(str, exp) { \ + double _then, _now; \ + _then = gettime(); \ + exp; \ + _now = gettime(); \ + printf(str " took %f us/sample\n", 1000000.0 * (_now-_then) / (double)SIZE); \ +} +#endif + +static inline double gettime() +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return (double)(tv.tv_usec * 1.0e-6) + (double)(tv.tv_sec); +} + +#endif diff --git a/tests/interleavetest.c b/tests/interleavetest.c new file mode 100644 index 0000000..f03544f --- /dev/null +++ b/tests/interleavetest.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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. + * + * $Id: interleavetest.c $ + */ + +#include +#include +#include +#include + +#include "gdither.h" + +#define SIZE 20 +#define IL 5 + +int main(int argc, char *argv[]) +{ + float in[SIZE]; + int16_t out16[SIZE * IL]; + int32_t out32[SIZE * IL]; + int i, j; + GDither d16 = gdither_new(GDitherNone, IL, GDither16bit, 16); + GDither d32 = gdither_new(GDitherNone, IL, GDither32bit, 16); + + printf("checking interleaving\n"); + + for (j=0; j +#include +#include +#include +#include +#include + +#define SIZE 1024 + +#include "gdither.h" +#include "noise.h" +#include "compare.h" +#include "gettime.h" + +#define REPS 10000 +#define CYCLES 500.0 + +#define BINS 65536 + +int main(int argc, char *argv[]) +{ + unsigned int i, j; + fftw_complex *out = fftw_malloc(sizeof(fftw_complex) * (SIZE + 1)); + fftw_plan plan_rc; + double in[SIZE], sum[SIZE/2]; + int distrib[BINS]; + double min = 1e10; + double max = 0.0; + int min_f = 1000; + int max_f = 0; + + for (i=0; i max) { + max = sum[i]; + } else if (sum[i] < min) { + min = sum[i]; + } + //printf("%d\t%f\n", i, sum[i]); + } + + min /= REPS*16; + max /= REPS*16; + printf("random amp/frequecy range = [%.2f,%.2f]\n", min, max); + if (max - min > 0.03) { + printf("min-max range exceeds 0.03, seems excessive, failing\n"); + exit(1); + } + + for (i=0; i max_f) { + max_f = distrib[i]; + } + if (distrib[i] < min_f) { + min_f = distrib[i]; + } + } + printf("16bit distribution range = [%.2f,%.2f]\n", min_f/CYCLES, + max_f/CYCLES); + if (min_f/CYCLES < 0.8 || max_f/CYCLES > 1.25) { + printf("range seems excessive, failing\n"); + exit(1); + } + printf("ok\n"); + + return 0; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/tests/runcheck.c b/tests/runcheck.c new file mode 100644 index 0000000..b0b778b --- /dev/null +++ b/tests/runcheck.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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. + * + * $Id: runcheck.c $ + */ + +#include +#include +#include +#include +#include + +#define SIZE 1024 + +#include "gdither.h" +#include "compare.h" +#include "gettime.h" + +inline static float noise() +{ + static unsigned long rnd = 23232323; + rnd = (rnd * 196314165) + 907633515; + + return rnd * 2.3283064365387e-10f; +} + +int main(int argc, char *argv[]) +{ + GDither ds; + float in[SIZE]; + double ind[SIZE]; + int32_t out32[SIZE]; + int16_t out16[SIZE]; + float outf[SIZE]; + int i; + + for (i=0; i 0.00001f) { + fprintf(stderr, "bad float rounding: %d\t%f\n", i, + outf[i] * 128.0f); + fprintf(stderr, "failing\n"); + exit(1); + } + } + gdither_free(ds); + + /* Warm up the buffers and so on */ + ds = gdither_new(GDitherNone, 1, 23, 0); + gdither_runf(ds, 0, SIZE, in, out32); + + TIME("baseline 24 in 32 test, 1024 samples", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + printf("\nOptimised:\n"); + + + ds = gdither_new(GDitherNone, 1, GDither32bit, 24); + TIME("GDitherNone, 1024 samples, 24 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherRect, 1, GDither32bit, 24); + TIME("GDitherRect, 1024 samples, 24 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherTri, 1, GDither32bit, 24); + TIME("GDitherTri, 1024 samples, 24 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherShaped, 1, GDither32bit, 24); + TIME("GDitherShaped, 1024 samples, 24 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + printf("\n"); + + ds = gdither_new(GDitherNone, 1, GDither16bit, 0); + TIME("GDitherNone, 1024 samples, 16bit", + gdither_runf(ds, 0, SIZE, in, out16)); + gdither_free(ds); + + ds = gdither_new(GDitherRect, 1, GDither16bit, 0); + TIME("GDitherRect, 1024 samples, 16bit", + gdither_runf(ds, 0, SIZE, in, out16)); + gdither_free(ds); + + ds = gdither_new(GDitherTri, 1, GDither16bit, 0); + TIME("GDitherTri, 1024 samples, 16bit", + gdither_runf(ds, 0, SIZE, in, out16)); + gdither_free(ds); + + ds = gdither_new(GDitherShaped, 1, GDither16bit, 0); + TIME("GDitherShaped, 1024 samples, 16bit", + gdither_runf(ds, 0, SIZE, in, out16)); + gdither_free(ds); + + printf("\nUnoptimised:\n"); + + ds = gdither_new(GDitherNone, 1, GDither32bit, 20); + TIME("GDitherNone, 1024 samples, 20 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherRect, 1, GDither32bit, 20); + TIME("GDitherRect, 1024 samples, 20 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherTri, 1, GDither32bit, 20); + TIME("GDitherTri, 1024 samples, 20 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + ds = gdither_new(GDitherShaped, 1, GDither32bit, 20); + TIME("GDitherShaped, 1024 samples, 20 in 32bit", + gdither_runf(ds, 0, SIZE, in, out32)); + gdither_free(ds); + + printf("\n"); + + ds = gdither_new(GDitherNone, 1, GDitherFloat, 20); + TIME("GDitherNone, 1024 samples, 24 in float", + gdither_runf(ds, 0, SIZE, in, outf)); + gdither_free(ds); + + ds = gdither_new(GDitherRect, 1, GDitherFloat, 20); + TIME("GDitherRect, 1024 samples, 24 in float", + gdither_runf(ds, 0, SIZE, in, outf)); + gdither_free(ds); + + ds = gdither_new(GDitherTri, 1, GDitherFloat, 20); + TIME("GDitherTri, 1024 samples, 24 in float", + gdither_runf(ds, 0, SIZE, in, outf)); + gdither_free(ds); + + ds = gdither_new(GDitherShaped, 1, GDitherFloat, 20); + TIME("GDitherShaped, 1024 samples, 24 in float", + gdither_runf(ds, 0, SIZE, in, outf)); + gdither_free(ds); + + printf("\n"); + + ds = gdither_new(GDitherTri, 1, GDitherFloat, 20); + TIME("GDitherTri, 1024 samples, 24 in float, double input", + gdither_run(ds, 0, SIZE, ind, outf)); + gdither_free(ds); + + return 0; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/tests/shapeplot.c b/tests/shapeplot.c new file mode 100644 index 0000000..cff09bc --- /dev/null +++ b/tests/shapeplot.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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. + * + * $Id: distortion-test.c $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gdither.h" + +#define SIZE 16384 + +#ifndef M_PI +#define M_PI 3.1415926 +#endif + +float in[SIZE]; +int32_t out[SIZE]; +double sin_tbl[SIZE]; +double sinless_tbl[SIZE]; + +void mkdata(GDitherType dt, const char *desc); + +int main(int argc, char *argv[]) +{ + int i; + + for (i=0; i