reverted generic Makefile, fixed Xscale default value in STRETCH mode, added support for anti-aliasing !

This commit is contained in:
ekeeke31 2008-10-20 15:50:13 +00:00
parent 6d34bb5796
commit ef3f88e060
22 changed files with 367970 additions and 99 deletions

View File

@ -1,23 +0,0 @@
.PHONY = all wii gc wii-clean gc-clean wii-run gc-run
all: wii gc
clean: wii-clean gc-clean
wii:
$(MAKE) -f Makefile.wii
wii-clean:
$(MAKE) -f Makefile.wii clean
wii-run:
$(MAKE) -f Makefile.wii run
gc:
$(MAKE) -f Makefile.gc
gc-clean:
$(MAKE) -f Makefile.gc clean
gc-run:
$(MAKE) -f Makefile.gc run

6
compile_all.bat Normal file
View File

@ -0,0 +1,6 @@
cp Makefile.gc Makefile
make
cp Makefile.wii Makefile
make
rm Makefile
cp genplus_wii.dol boot.dol

View File

@ -15,18 +15,21 @@ CURRENT:
- improved HBLANK flag accuracy, fixes line flickering in "Gouketsuji Ichizoku"
- re-enabled Z80 banked access to WRAM, fixes hang-up in "Mamono Hunter Youko"
- modified JCART emulation, fixes corrupted tracks logo in "Micro Machines 2"
- added Blargg's NTSC Filters support
- added Blargg's NTSC Filters support (emulates NTSC composite video artifacts)
[NGC/Wii]
- remove unused libsamplerate settings in "HQ YM2612" mode
- implemented menu fast scrolling with the Wiimote D-PAD
- fixed config file incompatibilities between Gamecube and Wii versions
- re-enabled texture filtering in H40 original mode when overscan is emulated: fix screen scroll tearing
- remove useless libsamplerate settings in "HQ YM2612" mode, only keeps SRC_LINEAR (faster) and SRC_SINC_FAST (better)
- implemented fast scrolling in menus using Wiimote D-PAD
- fixed config file incompatibilities when switching between Gamecube and Wii versions
- added an option to enable/disable bilinear filtering (can reduce scroll tearing sometime)
- added antialiasing support (optional)
- modified Xscale/Yscale values to show scaled width/height instead of scaling offsets
- removed embedded font, back to internal IPL font: it should still works for Qoob users (thanks to emukiddid !)
[NGC]
- added proper 480p menu detection for NTSC Gamecube users
- now prevents FAT automatic operations if no SDCARD is inserted
- prevents FAT automatic operations if no SDCARD is present

View File

@ -4,7 +4,7 @@
#include <fat.h>
#include <sys/dir.h>
#define CONFIG_VERSION "GENPLUS 1.2.6 "
#define CONFIG_VERSION "GENPLUS 1.2.7 "
t_config config;
bool use_FAT;
@ -90,6 +90,7 @@ void set_config_defaults(void)
config.render = (vmode->viTVMode == VI_TVMODE_NTSC_PROG) ? 2 : 0;
config.ntsc = 0;
config.filtering = 1;
config.aa = 0;
/* controllers options */
ogc_input__set_defaults();

View File

@ -30,6 +30,7 @@ typedef struct
uint8 render;
uint8 ntsc;
uint8 filtering;
uint8 aa;
uint16 pad_keymap[4][MAX_KEYS];
uint32 wpad_keymap[4*3][MAX_KEYS];
t_input_config input[MAX_DEVICES];

View File

@ -314,8 +314,8 @@ void dispmenu ()
int ret;
int quit = 0;
int prevmenu = menu;
int count = config.aspect ? 8 : 10;
char items[10][25];
int count = 11;
char items[11][25];
strcpy (menutitle, "Press B to return");
menu = 0;
@ -331,16 +331,17 @@ void dispmenu ()
if (config.tv_mode == 0) sprintf (items[2], "TV Mode: 60HZ");
else if (config.tv_mode == 1) sprintf (items[2], "TV Mode: 50HZ");
else sprintf (items[2], "TV Mode: 50/60HZ");
sprintf (items[3], "GX Filter: %s", config.filtering ? " ON" : "OFF");
if (config.ntsc == 1) sprintf (items[4], "NTSC Filter: COMPOSITE");
else if (config.ntsc == 2) sprintf (items[4], "NTSC Filter: S-VIDEO");
else if (config.ntsc == 3) sprintf (items[4], "NTSC Filter: RGB");
else sprintf (items[4], "NTSC Filter: OFF");
sprintf (items[5], "Borders: %s", config.overscan ? " ON" : "OFF");
sprintf (items[6], "Center X: %s%02d", config.xshift < 0 ? "-":"+", abs(config.xshift));
sprintf (items[7], "Center Y: %s%02d", config.yshift < 0 ? "-":"+", abs(config.yshift));
sprintf (items[8], "Scale X: %02d", xscale*2);
sprintf (items[9], "Scale Y: %02d", yscale*2);
sprintf (items[3], "Anti Aliasing: %s", config.aa ? " ON" : "OFF");
sprintf (items[4], "GX Filter: %s", config.filtering ? " ON" : "OFF");
if (config.ntsc == 1) sprintf (items[5], "NTSC Filter: COMPOSITE");
else if (config.ntsc == 2) sprintf (items[5], "NTSC Filter: S-VIDEO");
else if (config.ntsc == 3) sprintf (items[5], "NTSC Filter: RGB");
else sprintf (items[5], "NTSC Filter: OFF");
sprintf (items[6], "Borders: %s", config.overscan ? " ON" : "OFF");
sprintf (items[7], "Center X: %s%02d", config.xshift < 0 ? "-":"+", abs(config.xshift));
sprintf (items[8], "Center Y: %s%02d", config.yshift < 0 ? "-":"+", abs(config.yshift));
sprintf (items[9], "Scale X: %02d", xscale*2);
sprintf (items[10], "Scale Y: %02d", yscale*2);
ret = domenu (&items[0], count, 1);
@ -348,7 +349,6 @@ void dispmenu ()
{
case 0: /*** config.aspect ratio ***/
config.aspect ^= 1;
count = config.aspect ? 8 : 10;
bitmap.viewport.changed = 1;
break;
@ -360,7 +360,6 @@ void dispmenu ()
{
/* progressive mode (60hz only) */
config.tv_mode = 0;
gc_pal = 0;
}
else
{
@ -376,44 +375,50 @@ void dispmenu ()
config.tv_mode = (config.tv_mode + 1) % 3;
break;
case 3: /*** texture filtering ***/
case 3: /*** antialiasing ***/
config.aa ^= 1;
break;
case 4: /*** bilinear filtering ***/
config.filtering ^= 1;
bitmap.viewport.changed = 1;
break;
case 4: /*** NTSC filter ***/
case 5: /*** NTSC filter ***/
config.ntsc ++;
if (config.ntsc > 3) config.ntsc = 0;
bitmap.viewport.changed = 1;
break;
case 5: /*** overscan emulation ***/
case 6: /*** overscan emulation ***/
config.overscan ^= 1;
bitmap.viewport.x = config.overscan ? ((reg[12] & 1) ? 16 : 12) : 0;
bitmap.viewport.y = config.overscan ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;
bitmap.viewport.changed = 1;
break;
case 6: /*** Center X ***/
case -8:
case 7: /*** Center X ***/
case -9:
if (ret<0) config.xshift --;
else config.xshift ++;
break;
case 7: /*** Center Y ***/
case -9:
case 8: /*** Center Y ***/
case -10:
if (ret<0) config.yshift --;
else config.yshift ++;
break;
case 8: /*** Scale X ***/
case -10:
if (ret<0) config.xscale --;
case 9: /*** Scale X ***/
case -11:
if (config.aspect) break;
if (ret<0) config.xscale --;
else config.xscale ++;
break;
case 9: /*** Scale Y ***/
case -11:
case 10: /*** Scale Y ***/
case -12:
if (config.aspect) break;
if (ret<0) config.yscale --;
else config.yscale ++;
break;

View File

@ -70,12 +70,12 @@ GXRModeObj TV50hz_288p =
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
@ -107,10 +107,10 @@ GXRModeObj TV50hz_288i =
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
@ -140,23 +140,23 @@ GXRModeObj TV50hz_576i =
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
// vertical filter[7], 1/64 units, 6 bits each
{
4, // line n-1
8, // line n-1
8, // line n-1
10, // line n
12, // line n
10, // line n
16, // line n
12, // line n
8, // line n+1
8 // line n+1
4 // line n+1
}
};
@ -175,12 +175,12 @@ GXRModeObj TV60hz_240p =
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
@ -212,10 +212,10 @@ GXRModeObj TV60hz_240i =
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
@ -245,23 +245,23 @@ GXRModeObj TV60hz_480i =
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
// vertical filter[7], 1/64 units, 6 bits each
{
4, // line n-1
8, // line n-1
8, // line n-1
10, // line n
12, // line n
10, // line n
16, // line n
12, // line n
8, // line n+1
8 // line n+1
4 // line n+1
}
};
@ -406,7 +406,7 @@ void ogc_video__scale(void)
else
{
/* fullscreen stretch */
xscale = bitmap.viewport.w + 2*bitmap.viewport.x;
xscale = 352;
yscale = (gc_pal && !config.render) ? (vdp_pal ? (268*144 / bitmap.viewport.h):143) : (vdp_pal ? (224*144 / bitmap.viewport.h):120);
}
@ -469,9 +469,14 @@ void ogc_video__scale(void)
square[0] = square[9] = -scale + xshift;
/* vertical scaling */
scale = yscale;
square[4] = square[1] = (scale + yshift) * (config.render ? 2:1);
square[7] = square[10] = (yshift - scale) * (config.render ? 2:1);
scale = yscale + yshift;
if (config.render && !config.aa)
{
scale *= 2;
yshift *= 2;
}
square[4] = square[1] = scale + yshift;
square[7] = square[10] = yshift - scale;
/* update position matrix */
draw_init();
@ -504,6 +509,11 @@ void ogc_video__reset()
if (config.render) rmode = tvmodes[gc_pal*3 + 2];
else rmode = tvmodes[gc_pal*3 + interlaced];
/* anti-aliasing */
rmode->aa = config.aa;
if (config.render) rmode->efbHeight = config.aa ? 242 : 480;
else if (gc_pal) rmode->efbHeight = config.aa ? 264 : 286;
VIDEO_Configure (rmode);
VIDEO_ClearFrameBuffer(rmode, xfb[whichfb], COLOR_BLACK);
VIDEO_Flush();
@ -521,7 +531,7 @@ void ogc_video__reset()
GX_SetDispCopyDst (rmode->fbWidth, xfbHeight);
GX_SetCopyFilter (rmode->aa, rmode->sample_pattern, config.render ? GX_TRUE : GX_FALSE, rmode->vfilter);
GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR);
GX_SetPixelFmt (rmode->aa ? GX_PF_RGB565_Z16 : GX_PF_RGB8_Z24, GX_ZC_LINEAR);
guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 100, 1000);
GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC);

1
source/sound/SRC/AUTHORS Normal file
View File

@ -0,0 +1 @@
Erik de Castro Lopo <erikd@mega-nerd.com>

340
source/sound/SRC/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 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.
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.
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.)
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.
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.
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
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) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year 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.

23
source/sound/SRC/NEWS Normal file
View File

@ -0,0 +1,23 @@
Version 0.1.4 (2008-07-02)
* Fix bug which causes a segfault with extremely low conversion ratios.
Version 0.1.3 (2008-03-23)
* Huge improvement to the quality of conversion with the
SRC_SINC_MEDIUM_QUALITY and SRC_SINC_BEST_QUALITY converters.
* Minor bug fixes.
Version 0.1.2 (2004-09-12)
* Fixed where callback based API wasn't being reset properly.
* Minor bug fixes.
Version 0.1.1 (2004-07-17)
* Fixed bug in callback based API.
* Fixed a bug brought to light by aggressive optimisations of gcc-3.4.
* Minor bug fixes.
Version 0.1.0 (2004-03-14)
* Added callback based API.
* Added a pair of functions for doing short to float and float to short
conversions on an arrays of data.
* Many minor bug fixes.

50
source/sound/SRC/README Normal file
View File

@ -0,0 +1,50 @@
This is libsamplerate, 0.1.4
libsamplerate (also known as Secret Rabbit Code) is a library for
perfroming sample rate conversion of audio data.
The src/ directory contains the source code for library itself.
The doc/ directory contains the libsamplerate documentation.
The examples/ directory contains examples of how to write code using
libsamplerate.
The tests/ directory contains programs which link against
libsamplerate and test its functionality.
The Win32/ directory contains files and documentation to allow
libsamplerate to compile under Win32 with the Microsoft Visual C++
compiler.
Win32
-----
There are detailed instructions for building libsamplerate on Win32
in the file
doc/win32.html
MacOSX
------
Building on MacOSX should be the same as building it on any other
Unix.
OTHER PLATFORMS
---------------
To compile libsamplerate on platforms which have a Bourne Shell compatible
shell, an ANSI C compiler and a make utility should require no more that
the following three commands :
./configure
make
make install
CONTACTS
--------
libsamplerate was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
The libsamplerate home page is at :
http://www.mega-nerd.com/libsamplerate/

148
source/sound/SRC/common.h Normal file
View File

@ -0,0 +1,148 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif (SIZEOF_INT == 4)
typedef int int32_t ;
#elif (SIZEOF_LONG == 4)
typedef long int32_t ;
#endif
#define SRC_MAX_RATIO 256
#define SRC_MIN_RATIO_DIFF (1e-20)
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
#define OFFSETOF(type,member) ((int) (&((type*) 0)->member))
#define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20))
#include "samplerate.h"
enum
{ SRC_FALSE = 0,
SRC_TRUE = 1,
SRC_MODE_PROCESS = 555,
SRC_MODE_CALLBACK = 556
} ;
enum
{ SRC_ERR_NO_ERROR = 0,
SRC_ERR_MALLOC_FAILED,
SRC_ERR_BAD_STATE,
SRC_ERR_BAD_DATA,
SRC_ERR_BAD_DATA_PTR,
SRC_ERR_NO_PRIVATE,
SRC_ERR_BAD_SRC_RATIO,
SRC_ERR_BAD_PROC_PTR,
SRC_ERR_SHIFT_BITS,
SRC_ERR_FILTER_LEN,
SRC_ERR_BAD_CONVERTER,
SRC_ERR_BAD_CHANNEL_COUNT,
SRC_ERR_SINC_BAD_BUFFER_LEN,
SRC_ERR_SIZE_INCOMPATIBILITY,
SRC_ERR_BAD_PRIV_PTR,
SRC_ERR_BAD_SINC_STATE,
SRC_ERR_DATA_OVERLAP,
SRC_ERR_BAD_CALLBACK,
SRC_ERR_BAD_MODE,
SRC_ERR_NULL_CALLBACK,
SRC_ERR_NO_VARIABLE_RATIO,
/* This must be the last error number. */
SRC_ERR_MAX_ERROR
} ;
typedef struct SRC_PRIVATE_tag
{ double last_ratio, last_position ;
int error ;
int channels ;
/* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */
int mode ;
/* Pointer to data to converter specific data. */
void *private_data ;
/* Varispeed process function. */
int (*vari_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
/* Constant speed process function. */
int (*const_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
/* State reset. */
void (*reset) (struct SRC_PRIVATE_tag *psrc) ;
/* Data specific to SRC_MODE_CALLBACK. */
src_callback_t callback_func ;
void *user_callback_data ;
long saved_frames ;
float *saved_data ;
} SRC_PRIVATE ;
/* In src_sinc.c */
const char* sinc_get_name (int src_enum) ;
const char* sinc_get_description (int src_enum) ;
int sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) ;
/* In src_linear.c */
const char* linear_get_name (int src_enum) ;
const char* linear_get_description (int src_enum) ;
int linear_set_converter (SRC_PRIVATE *psrc, int src_enum) ;
/* In src_zoh.c */
const char* zoh_get_name (int src_enum) ;
const char* zoh_get_description (int src_enum) ;
int zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) ;
/*----------------------------------------------------------
** Common static inline functions.
*/
static inline double
fmod_one (double x)
{ double res ;
res = x - lrint (x) ;
if (res < 0.0)
return res + 1.0 ;
return res ;
} /* fmod_one */
#endif /* COMMON_H_INCLUDED */

143
source/sound/SRC/config.h Normal file
View File

@ -0,0 +1,143 @@
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Set to 1 if the compile is GNU GCC. */
#undef COMPILER_IS_GCC
/* Target processor clips on negative float to int conversion. */
#define CPU_CLIPS_NEGATIVE 0
/* Target processor clips on positive float to int conversion. */
#define CPU_CLIPS_POSITIVE 0
/* Target processor is big endian. */
#undef CPU_IS_BIG_ENDIAN
/* Target processor is little endian. */
#undef CPU_IS_LITTLE_ENDIAN
/* Major version of GCC or 3 otherwise. */
#undef GCC_MAJOR_VERSION
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
/* Define to 1 if you have the `calloc' function. */
#undef HAVE_CALLOC
/* Define to 1 if you have the `ceil' function. */
#undef HAVE_CEIL
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Set to 1 if you have libfftw3. */
#undef HAVE_FFTW3
/* Define to 1 if you have the `floor' function. */
#undef HAVE_FLOOR
/* Define to 1 if you have the `fmod' function. */
#undef HAVE_FMOD
/* Define to 1 if you have the `free' function. */
#undef HAVE_FREE
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define if you have C99's lrint function. */
#ifdef DOS
#define HAVE_LRINT 0
#else
#define HAVE_LRINT 1
#endif
/* Define if you have C99's lrintf function. */
#define HAVE_LRINTF 1
/* Define to 1 if you have the `malloc' function. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have signal SIGALRM. */
#undef HAVE_SIGALRM
/* Define to 1 if you have the `signal' function. */
#undef HAVE_SIGNAL
/* Set to 1 if you have libsndfile. */
#undef HAVE_SNDFILE
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Set to 1 if compiling for Win32 */
#undef OS_IS_WIN32
/* Name of package */
#define PACKAGE "OGC"
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `double', as computed by sizeof. */
#undef SIZEOF_DOUBLE
/* The size of `float', as computed by sizeof. */
#undef SIZEOF_FLOAT
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#define VERSION "0.1.4"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,255 @@
/*
** Copyright (C) 2001-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Version 1.4 */
#ifndef FLOAT_CAST_HEADER
#define FLOAT_CAST_HEADER
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x) ;
** long int lrint (double x) ;
*/
#include "config.h"
/*
** The presence of the required functions are detected during the configure
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
** the config.h file.
*/
#define HAVE_LRINT_REPLACEMENT 0
#if (HAVE_LRINT && HAVE_LRINTF)
/*
** These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#elif (defined (__CYGWIN__))
#include <math.h>
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
/*
** The native CYGWIN lrint and lrintf functions are buggy:
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
** and slow.
** These functions (pulled from the Public Domain MinGW math.h header)
** replace the native versions.
*/
static inline long double2int (double in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* double2int */
static inline long float2int (float in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* float2int */
#elif (defined (WIN32) || defined (_WIN32))
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
/*
** Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here.
*/
__inline long int
lrint (double flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
__inline long int
lrintf (float flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
#elif (defined (__MWERKS__) && defined (macintosh))
/* This MacOS 9 solution was provided by Stephane Letz */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline int
float2int (register float in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* float2int */
inline int
double2int (register double in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* double2int */
#elif (defined (__MACH__) && defined (__APPLE__))
/* For Apple MacOSX. */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline static long
float2int (register float in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrintf */
inline static long
double2int (register double in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrint */
#else
#ifndef __sgi
#warning "Don't have the functions lrint() and lrintf()."
#warning "Replacing these functions with a standard C cast."
#endif
#include <math.h>
#define lrint(dbl) ((long) (dbl))
#define lrintf(flt) ((long) (flt))
#endif
#endif /* FLOAT_CAST_HEADER */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,539 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "samplerate.h"
#include "float_cast.h"
#include "common.h"
static int psrc_set_converter (SRC_PRIVATE *psrc, int converter_type) ;
static inline int
is_bad_src_ratio (double ratio)
{ return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ;
} /* is_bad_src_ratio */
SRC_STATE *
src_new (int converter_type, int channels, int *error)
{ SRC_PRIVATE *psrc ;
if (error)
*error = SRC_ERR_NO_ERROR ;
if (channels < 1)
{ if (error)
*error = SRC_ERR_BAD_CHANNEL_COUNT ;
return NULL ;
} ;
if ((psrc = calloc (1, sizeof (*psrc))) == NULL)
{ if (error)
*error = SRC_ERR_MALLOC_FAILED ;
return NULL ;
} ;
psrc->channels = channels ;
psrc->mode = SRC_MODE_PROCESS ;
if (psrc_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR)
{ if (error)
*error = SRC_ERR_BAD_CONVERTER ;
free (psrc) ;
psrc = NULL ;
} ;
src_reset ((SRC_STATE*) psrc) ;
return (SRC_STATE*) psrc ;
} /* src_new */
SRC_STATE*
src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data)
{ SRC_STATE *src_state ;
if (func == NULL)
{ if (error)
*error = SRC_ERR_BAD_CALLBACK ;
return NULL ;
} ;
if (error != NULL)
*error = 0 ;
src_state = src_new (converter_type, channels, error) ;
src_reset (src_state) ;
((SRC_PRIVATE*) src_state)->mode = SRC_MODE_CALLBACK ;
((SRC_PRIVATE*) src_state)->callback_func = func ;
((SRC_PRIVATE*) src_state)->user_callback_data = cb_data ;
return src_state ;
} /* src_callback_new */
SRC_STATE *
src_delete (SRC_STATE *state)
{ SRC_PRIVATE *psrc ;
psrc = (SRC_PRIVATE*) state ;
if (psrc)
{ if (psrc->private_data)
free (psrc->private_data) ;
memset (psrc, 0, sizeof (SRC_PRIVATE)) ;
free (psrc) ;
} ;
return NULL ;
} /* src_state */
int
src_process (SRC_STATE *state, SRC_DATA *data)
{ SRC_PRIVATE *psrc ;
int error ;
psrc = (SRC_PRIVATE*) state ;
if (psrc == NULL)
return SRC_ERR_BAD_STATE ;
if (psrc->vari_process == NULL || psrc->const_process == NULL)
return SRC_ERR_BAD_PROC_PTR ;
if (psrc->mode != SRC_MODE_PROCESS)
return SRC_ERR_BAD_MODE ;
/* Check for valid SRC_DATA first. */
if (data == NULL)
return SRC_ERR_BAD_DATA ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (data->src_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
/* And that data_in and data_out are valid. */
if (data->data_in == NULL || data->data_out == NULL)
return SRC_ERR_BAD_DATA_PTR ;
if (data->data_in == NULL)
data->input_frames = 0 ;
if (data->input_frames < 0)
data->input_frames = 0 ;
if (data->output_frames < 0)
data->output_frames = 0 ;
if (data->data_in < data->data_out)
{ if (data->data_in + data->input_frames * psrc->channels > data->data_out)
{ /*-printf ("\n\ndata_in: %p data_out: %p\n",
(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/
return SRC_ERR_DATA_OVERLAP ;
} ;
}
else if (data->data_out + data->output_frames * psrc->channels > data->data_in)
{ /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;
printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out,
(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/
return SRC_ERR_DATA_OVERLAP ;
} ;
/* Set the input and output counts to zero. */
data->input_frames_used = 0 ;
data->output_frames_gen = 0 ;
/* Special case for when last_ratio has not been set. */
if (psrc->last_ratio < (1.0 / SRC_MAX_RATIO))
psrc->last_ratio = data->src_ratio ;
/* Now process. */
if (fabs (psrc->last_ratio - data->src_ratio) < 1e-15)
error = psrc->const_process (psrc, data) ;
else
error = psrc->vari_process (psrc, data) ;
return error ;
} /* src_process */
long
src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
{ SRC_PRIVATE *psrc ;
SRC_DATA src_data ;
long output_frames_gen ;
int error = 0 ;
if (state == NULL)
return 0 ;
if (frames <= 0)
return 0 ;
psrc = (SRC_PRIVATE*) state ;
if (psrc->mode != SRC_MODE_CALLBACK)
{ psrc->error = SRC_ERR_BAD_MODE ;
return 0 ;
} ;
if (psrc->callback_func == NULL)
{ psrc->error = SRC_ERR_NULL_CALLBACK ;
return 0 ;
} ;
memset (&src_data, 0, sizeof (src_data)) ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (src_ratio))
{ psrc->error = SRC_ERR_BAD_SRC_RATIO ;
return 0 ;
} ;
/* Switch modes temporarily. */
src_data.src_ratio = src_ratio ;
src_data.data_out = data ;
src_data.output_frames = frames ;
src_data.data_in = psrc->saved_data ;
src_data.input_frames = psrc->saved_frames ;
output_frames_gen = 0 ;
while (output_frames_gen < frames)
{
if (src_data.input_frames == 0)
{ float *ptr ;
src_data.input_frames = psrc->callback_func (psrc->user_callback_data, &ptr) ;
src_data.data_in = ptr ;
if (src_data.input_frames == 0)
src_data.end_of_input = 1 ;
} ;
/*
** Now call process function. However, we need to set the mode
** to SRC_MODE_PROCESS first and when we return set it back to
** SRC_MODE_CALLBACK.
*/
psrc->mode = SRC_MODE_PROCESS ;
error = src_process (state, &src_data) ;
psrc->mode = SRC_MODE_CALLBACK ;
if (error != 0)
break ;
src_data.data_in += src_data.input_frames_used * psrc->channels ;
src_data.input_frames -= src_data.input_frames_used ;
src_data.data_out += src_data.output_frames_gen * psrc->channels ;
src_data.output_frames -= src_data.output_frames_gen ;
output_frames_gen += src_data.output_frames_gen ;
if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0)
break ;
} ;
psrc->saved_data = src_data.data_in ;
psrc->saved_frames = src_data.input_frames ;
if (error != 0)
{ psrc->error = error ;
return 0 ;
} ;
return output_frames_gen ;
} /* src_callback_read */
/*==========================================================================
*/
int
src_set_ratio (SRC_STATE *state, double new_ratio)
{ SRC_PRIVATE *psrc ;
psrc = (SRC_PRIVATE*) state ;
if (psrc == NULL)
return SRC_ERR_BAD_STATE ;
if (psrc->vari_process == NULL || psrc->const_process == NULL)
return SRC_ERR_BAD_PROC_PTR ;
if (is_bad_src_ratio (new_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
psrc->last_ratio = new_ratio ;
return SRC_ERR_NO_ERROR ;
} /* src_set_ratio */
int
src_reset (SRC_STATE *state)
{ SRC_PRIVATE *psrc ;
if ((psrc = (SRC_PRIVATE*) state) == NULL)
return SRC_ERR_BAD_STATE ;
if (psrc->reset != NULL)
psrc->reset (psrc) ;
psrc->last_position = 0.0 ;
psrc->last_ratio = 0.0 ;
psrc->saved_data = NULL ;
psrc->saved_frames = 0 ;
psrc->error = SRC_ERR_NO_ERROR ;
return SRC_ERR_NO_ERROR ;
} /* src_reset */
/*==============================================================================
** Control functions.
*/
const char *
src_get_name (int converter_type)
{ const char *desc ;
if ((desc = sinc_get_name (converter_type)) != NULL)
return desc ;
if ((desc = zoh_get_name (converter_type)) != NULL)
return desc ;
if ((desc = linear_get_name (converter_type)) != NULL)
return desc ;
return NULL ;
} /* src_get_name */
const char *
src_get_description (int converter_type)
{ const char *desc ;
if ((desc = sinc_get_description (converter_type)) != NULL)
return desc ;
if ((desc = zoh_get_description (converter_type)) != NULL)
return desc ;
if ((desc = linear_get_description (converter_type)) != NULL)
return desc ;
return NULL ;
} /* src_get_description */
const char *
src_get_version (void)
{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;
} /* src_get_version */
int
src_is_valid_ratio (double ratio)
{
if (is_bad_src_ratio (ratio))
return SRC_FALSE ;
return SRC_TRUE ;
} /* src_is_valid_ratio */
/*==============================================================================
** Error reporting functions.
*/
int
src_error (SRC_STATE *state)
{ if (state)
return ((SRC_PRIVATE*) state)->error ;
return SRC_ERR_NO_ERROR ;
} /* src_error */
const char*
src_strerror (int error)
{
switch (error)
{ case SRC_ERR_NO_ERROR :
return "No error." ;
case SRC_ERR_MALLOC_FAILED :
return "Malloc failed." ;
case SRC_ERR_BAD_STATE :
return "SRC_STATE pointer is NULL." ;
case SRC_ERR_BAD_DATA :
return "SRC_DATA pointer is NULL." ;
case SRC_ERR_BAD_DATA_PTR :
return "SRC_DATA->data_out is NULL." ;
case SRC_ERR_NO_PRIVATE :
return "Internal error. No private data." ;
case SRC_ERR_BAD_SRC_RATIO :
return "SRC ratio outside [1/12, 12] range." ;
case SRC_ERR_BAD_SINC_STATE :
return "src_process() called without reset after end_of_input." ;
case SRC_ERR_BAD_PROC_PTR :
return "Internal error. No process pointer." ;
case SRC_ERR_SHIFT_BITS :
return "Internal error. SHIFT_BITS too large." ;
case SRC_ERR_FILTER_LEN :
return "Internal error. Filter length too large." ;
case SRC_ERR_BAD_CONVERTER :
return "Bad converter number." ;
case SRC_ERR_BAD_CHANNEL_COUNT :
return "Channel count must be >= 1." ;
case SRC_ERR_SINC_BAD_BUFFER_LEN :
return "Internal error. Bad buffer length. Please report this." ;
case SRC_ERR_SIZE_INCOMPATIBILITY :
return "Internal error. Input data / internal buffer size difference. Please report this." ;
case SRC_ERR_BAD_PRIV_PTR :
return "Internal error. Private pointer is NULL. Please report this." ;
case SRC_ERR_DATA_OVERLAP :
return "Input and output data arrays overlap." ;
case SRC_ERR_BAD_CALLBACK :
return "Supplied callback function pointer is NULL." ;
case SRC_ERR_BAD_MODE :
return "Calling mode differs from initialisation mode (ie process v callback)." ;
case SRC_ERR_NULL_CALLBACK :
return "Callback function pointer is NULL in src_callback_read ()." ;
case SRC_ERR_NO_VARIABLE_RATIO :
return "This converter only allows constant conversion ratios." ;
case SRC_ERR_MAX_ERROR :
return "Placeholder. No error defined for this error number." ;
default : break ;
}
return NULL ;
} /* src_strerror */
/*==============================================================================
** Simple interface for performing a single conversion from input buffer to
** output buffer at a fixed conversion ratio.
*/
int
src_simple (SRC_DATA *src_data, int converter, int channels)
{ SRC_STATE *src_state ;
int error ;
if ((src_state = src_new (converter, channels, &error)) == NULL)
return error ;
src_data->end_of_input = 1 ; /* Only one buffer worth of input. */
error = src_process (src_state, src_data) ;
src_state = src_delete (src_state) ;
return error ;
} /* src_simple */
void
src_short_to_float_array (const short *in, float *out, int len)
{
while (len)
{ len -- ;
out [len] = (float) (in [len] / (1.0 * 0x8000)) ;
} ;
return ;
} /* src_short_to_float_array */
void
src_float_to_short_array (const float *in, short *out, int len)
{ double scaled_value ;
while (len)
{ len -- ;
scaled_value = in [len] * (8.0 * 0x10000000) ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
{ out [len] = 32767 ;
continue ;
} ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
{ out [len] = -32768 ;
continue ;
} ;
out [len] = (short) (lrint (scaled_value) >> 16) ;
} ;
} /* src_float_to_short_array */
void
src_int_to_float_array (const int *in, float *out, int len)
{
while (len)
{ len -- ;
out [len] = (float) (in [len] / (8.0 * 0x10000000)) ;
} ;
return ;
} /* src_int_to_float_array */
void
src_float_to_int_array (const float *in, int *out, int len)
{ double scaled_value ;
while (len)
{ len -- ;
scaled_value = in [len] * (8.0 * 0x10000000) ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
{ out [len] = 0x7fffffff ;
continue ;
} ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
{ out [len] = -1 - 0x7fffffff ;
continue ;
} ;
out [len] = lrint (scaled_value) ;
} ;
} /* src_float_to_int_array */
/*==============================================================================
** Private functions.
*/
static int
psrc_set_converter (SRC_PRIVATE *psrc, int converter_type)
{
if (sinc_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
return SRC_ERR_NO_ERROR ;
if (zoh_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
return SRC_ERR_NO_ERROR ;
if (linear_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
return SRC_ERR_NO_ERROR ;
return SRC_ERR_BAD_CONVERTER ;
} /* psrc_set_converter */

View File

@ -0,0 +1,197 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
/*
** API documentation is available here:
** http://www.mega-nerd.com/SRC/api.html
*/
#ifndef SAMPLERATE_H
#define SAMPLERATE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Opaque data type SRC_STATE. */
typedef struct SRC_STATE_tag SRC_STATE ;
/* SRC_DATA is used to pass data to src_simple() and src_process(). */
typedef struct
{ float *data_in, *data_out ;
long input_frames, output_frames ;
long input_frames_used, output_frames_gen ;
int end_of_input ;
double src_ratio ;
} SRC_DATA ;
/* SRC_CB_DATA is used with callback based API. */
typedef struct
{ long frames ;
float *data_in ;
} SRC_CB_DATA ;
/*
** User supplied callback function type for use with src_callback_new()
** and src_callback_read(). First parameter is the same pointer that was
** passed into src_callback_new(). Second parameter is pointer to a
** pointer. The user supplied callback function must modify *data to
** point to the start of the user supplied float array. The user supplied
** function must return the number of frames that **data points to.
*/
typedef long (*src_callback_t) (void *cb_data, float **data) ;
/*
** Standard initialisation function : return an anonymous pointer to the
** internal state of the converter. Choose a converter from the enums below.
** Error returned in *error.
*/
SRC_STATE* src_new (int converter_type, int channels, int *error) ;
/*
** Initilisation for callback based API : return an anonymous pointer to the
** internal state of the converter. Choose a converter from the enums below.
** The cb_data pointer can point to any data or be set to NULL. Whatever the
** value, when processing, user supplied function "func" gets called with
** cb_data as first parameter.
*/
SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels,
int *error, void* cb_data) ;
/*
** Cleanup all internal allocations.
** Always returns NULL.
*/
SRC_STATE* src_delete (SRC_STATE *state) ;
/*
** Standard processing function.
** Returns non zero on error.
*/
int src_process (SRC_STATE *state, SRC_DATA *data) ;
/*
** Callback based processing function. Read up to frames worth of data from
** the converter int *data and return frames read or -1 on error.
*/
long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ;
/*
** Simple interface for performing a single conversion from input buffer to
** output buffer at a fixed conversion ratio.
** Simple interface does not require initialisation as it can only operate on
** a single buffer worth of audio.
*/
int src_simple (SRC_DATA *data, int converter_type, int channels) ;
/*
** This library contains a number of different sample rate converters,
** numbered 0 through N.
**
** Return a string giving either a name or a more full description of each
** sample rate converter or NULL if no sample rate converter exists for
** the given value. The converters are sequentially numbered from 0 to N.
*/
const char *src_get_name (int converter_type) ;
const char *src_get_description (int converter_type) ;
const char *src_get_version (void) ;
/*
** Set a new SRC ratio. This allows step responses
** in the conversion ratio.
** Returns non zero on error.
*/
int src_set_ratio (SRC_STATE *state, double new_ratio) ;
/*
** Reset the internal SRC state.
** Does not modify the quality settings.
** Does not free any memory allocations.
** Returns non zero on error.
*/
int src_reset (SRC_STATE *state) ;
/*
** Return TRUE if ratio is a valid conversion ratio, FALSE
** otherwise.
*/
int src_is_valid_ratio (double ratio) ;
/*
** Return an error number.
*/
int src_error (SRC_STATE *state) ;
/*
** Convert the error number into a string.
*/
const char* src_strerror (int error) ;
/*
** The following enums can be used to set the interpolator type
** using the function src_set_converter().
*/
enum
{
SRC_SINC_BEST_QUALITY = 0,
SRC_SINC_MEDIUM_QUALITY = 1,
SRC_SINC_FASTEST = 2,
SRC_ZERO_ORDER_HOLD = 3,
SRC_LINEAR = 4,
} ;
/*
** Extra helper functions for converting from short to float and
** back again.
*/
void src_short_to_float_array (const short *in, float *out, int len) ;
void src_float_to_short_array (const float *in, short *out, int len) ;
void src_int_to_float_array (const int *in, float *out, int len) ;
void src_float_to_int_array (const float *in, int *out, int len) ;
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* SAMPLERATE_H */

View File

@ -0,0 +1,219 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "float_cast.h"
#include "common.h"
static int linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static void linear_reset (SRC_PRIVATE *psrc) ;
/*========================================================================================
*/
#define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
#define SRC_DEBUG 0
typedef struct
{ int linear_magic_marker ;
int channels ;
int reset ;
long in_count, in_used ;
long out_count, out_gen ;
float last_value [1] ;
} LINEAR_DATA ;
/*----------------------------------------------------------------------------------------
*/
static int
linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ LINEAR_DATA *linear ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
linear = (LINEAR_DATA*) psrc->private_data ;
if (linear->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < linear->channels ; ch++)
linear->last_value [ch] = data->data_in [ch] ;
linear->reset = 0 ;
} ;
linear->in_count = data->input_frames * linear->channels ;
linear->out_count = data->output_frames * linear->channels ;
linear->in_used = linear->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
input_index = psrc->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && linear->out_gen < linear->out_count)
{
if (linear->in_used + linear->channels * input_index > linear->in_count)
break ;
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = (float) (linear->last_value [ch] + input_index *
(data->data_in [ch] - linear->last_value [ch])) ;
linear->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
} ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
{
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ;
exit (1) ;
} ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = (float) (data->data_in [linear->in_used - linear->channels + ch] + input_index *
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch])) ;
linear->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (linear->in_used > linear->in_count)
{ input_index += (linear->in_used - linear->in_count) / linear->channels ;
linear->in_used = linear->in_count ;
} ;
psrc->last_position = input_index ;
if (linear->in_used > 0)
for (ch = 0 ; ch < linear->channels ; ch++)
linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = linear->in_used / linear->channels ;
data->output_frames_gen = linear->out_gen / linear->channels ;
return SRC_ERR_NO_ERROR ;
} /* linear_vari_process */
/*------------------------------------------------------------------------------
*/
const char*
linear_get_name (int src_enum)
{
if (src_enum == SRC_LINEAR)
return "Linear Interpolator" ;
return NULL ;
} /* linear_get_name */
const char*
linear_get_description (int src_enum)
{
if (src_enum == SRC_LINEAR)
return "Linear interpolator, very fast, poor quality." ;
return NULL ;
} /* linear_get_descrition */
int
linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ LINEAR_DATA *linear = NULL ;
if (src_enum != SRC_LINEAR)
return SRC_ERR_BAD_CONVERTER ;
if (psrc->private_data != NULL)
{ linear = (LINEAR_DATA*) psrc->private_data ;
if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
} ;
if (psrc->private_data == NULL)
{ linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ;
if (linear == NULL)
return SRC_ERR_MALLOC_FAILED ;
psrc->private_data = linear ;
} ;
linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
linear->channels = psrc->channels ;
psrc->const_process = linear_vari_process ;
psrc->vari_process = linear_vari_process ;
psrc->reset = linear_reset ;
linear_reset (psrc) ;
return SRC_ERR_NO_ERROR ;
} /* linear_set_converter */
/*===================================================================================
*/
static void
linear_reset (SRC_PRIVATE *psrc)
{ LINEAR_DATA *linear = NULL ;
linear = (LINEAR_DATA*) psrc->private_data ;
if (linear == NULL)
return ;
linear->channels = psrc->channels ;
linear->reset = 1 ;
memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
} /* linear_reset */

478
source/sound/SRC/src_sinc.c Normal file
View File

@ -0,0 +1,478 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "float_cast.h"
#include "common.h"
#define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
/*========================================================================================
*/
#define MAKE_INCREMENT_T(x) ((increment_t) (x))
#define SHIFT_BITS 12
#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS))
#define INV_FP_ONE (1.0 / FP_ONE)
/*========================================================================================
*/
typedef int32_t increment_t ;
typedef float coeff_t ;
#include "fastest_coeffs.h"
#ifndef NGC
#include "mid_qual_coeffs.h"
#include "high_qual_coeffs.h"
#endif
typedef struct
{ int sinc_magic_marker ;
int channels ;
long in_count, in_used ;
long out_count, out_gen ;
int coeff_half_len, index_inc ;
double src_ratio, input_index ;
coeff_t const *coeffs ;
int b_current, b_end, b_real_end, b_len ;
float buffer [1] ;
} SINC_FILTER ;
static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ;
static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
static void sinc_reset (SRC_PRIVATE *psrc) ;
static inline increment_t
double_to_fp (double x)
{ if (sizeof (increment_t) == 8)
return (llrint ((x) * FP_ONE)) ;
return (lrint ((x) * FP_ONE)) ;
} /* double_to_fp */
static inline increment_t
int_to_fp (int x)
{ return (((increment_t) (x)) << SHIFT_BITS) ;
} /* int_to_fp */
static inline int
fp_to_int (increment_t x)
{ return (((x) >> SHIFT_BITS)) ;
} /* fp_to_int */
static inline increment_t
fp_fraction_part (increment_t x)
{ return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
} /* fp_fraction_part */
static inline double
fp_to_double (increment_t x)
{ return fp_fraction_part (x) * INV_FP_ONE ;
} /* fp_to_double */
/*----------------------------------------------------------------------------------------
*/
const char*
sinc_get_name (int src_enum)
{
switch (src_enum)
{
#ifndef NGC
case SRC_SINC_BEST_QUALITY :
return "Best Sinc Interpolator" ;
case SRC_SINC_MEDIUM_QUALITY :
return "Medium Sinc Interpolator" ;
#endif
case SRC_SINC_FASTEST :
return "Fastest Sinc Interpolator" ;
default: break ;
} ;
return NULL ;
} /* sinc_get_descrition */
const char*
sinc_get_description (int src_enum)
{
switch (src_enum)
{
#ifndef NGC
case SRC_SINC_FASTEST :
return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
case SRC_SINC_MEDIUM_QUALITY :
return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
#endif
case SRC_SINC_BEST_QUALITY :
return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
default :
break ;
} ;
return NULL ;
} /* sinc_get_descrition */
int
sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ SINC_FILTER *filter, temp_filter ;
increment_t count ;
int bits ;
/* Quick sanity check. */
if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
return SRC_ERR_SHIFT_BITS ;
if (psrc->private_data != NULL)
{ filter = (SINC_FILTER*) psrc->private_data ;
if (filter->sinc_magic_marker != SINC_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
} ;
memset (&temp_filter, 0, sizeof (temp_filter)) ;
temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
temp_filter.channels = psrc->channels ;
psrc->const_process = sinc_vari_process ;
psrc->vari_process = sinc_vari_process ;
psrc->reset = sinc_reset ;
switch (src_enum)
{ case SRC_SINC_FASTEST :
temp_filter.coeffs = fastest_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
temp_filter.index_inc = fastest_coeffs.increment ;
break ;
#ifndef NGC
case SRC_SINC_MEDIUM_QUALITY :
temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
break ;
case SRC_SINC_BEST_QUALITY :
temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
temp_filter.index_inc = slow_high_qual_coeffs.increment ;
break ;
#endif
default :
return SRC_ERR_BAD_CONVERTER ;
} ;
/*
** FIXME : This needs to be looked at more closely to see if there is
** a better way. Need to look at prepare_data () at the same time.
*/
temp_filter.b_len = 2 * lrint (1.0 + temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
temp_filter.b_len *= temp_filter.channels ;
if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
return SRC_ERR_MALLOC_FAILED ;
*filter = temp_filter ;
memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
psrc->private_data = filter ;
sinc_reset (psrc) ;
count = filter->coeff_half_len ;
for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
count |= (MAKE_INCREMENT_T (1) << bits) ;
if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
return SRC_ERR_FILTER_LEN ;
return SRC_ERR_NO_ERROR ;
} /* sinc_set_converter */
static void
sinc_reset (SRC_PRIVATE *psrc)
{ SINC_FILTER *filter ;
filter = (SINC_FILTER*) psrc->private_data ;
if (filter == NULL)
return ;
filter->b_current = filter->b_end = 0 ;
filter->b_real_end = -1 ;
filter->src_ratio = filter->input_index = 0.0 ;
memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ;
/* Set this for a sanity check */
memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
} /* sinc_reset */
/*========================================================================================
** Beware all ye who dare pass this point. There be dragons here.
*/
static int
sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand, ch ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
filter = (SINC_FILTER*) psrc->private_data ;
/* If there is not a problem, this will be optimised out. */
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
return SRC_ERR_SIZE_INCOMPATIBILITY ;
filter->in_count = data->input_frames * filter->channels ;
filter->out_count = data->output_frames * filter->channels ;
filter->in_used = filter->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
/* Check the sample rate ratio wrt the buffer len. */
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
count /= MIN (psrc->last_ratio, data->src_ratio) ;
/* Maximum coefficientson either side of center point. */
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
terminate = 1.0 / src_ratio + 1e-20 ;
/* Main processing loop. */
while (filter->out_gen < filter->out_count)
{
/* Need to reload buffer? */
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
{ prepare_data (filter, data, half_filter_chan_len) ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
break ;
} ;
/* This is the termination condition. */
if (filter->b_real_end >= 0)
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
break ;
} ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = double_to_fp (float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
for (ch = 0 ; ch < filter->channels ; ch++)
{ data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
calc_output (filter, increment, start_filter_index, ch)) ;
filter->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
} ;
psrc->last_position = input_index ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = filter->in_used / filter->channels ;
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_vari_process */
/*----------------------------------------------------------------------------------------
*/
static void
prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
{ int len = 0 ;
if (filter->b_real_end >= 0)
return ; /* This doesn't make sense, so return. */
if (filter->b_current == 0)
{ /* Initial state. Set up zeros at the start of the buffer and
** then load new data after that.
*/
len = filter->b_len - 2 * half_filter_chan_len ;
filter->b_current = filter->b_end = half_filter_chan_len ;
}
else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len)
{ /* Load data at current end position. */
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
}
else
{ /* Move data at end of buffer back to the start of the buffer. */
len = filter->b_end - filter->b_current ;
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
filter->b_current = half_filter_chan_len ;
filter->b_end = filter->b_current + len ;
/* Now load data at current end of buffer. */
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
} ;
len = MIN (filter->in_count - filter->in_used, len) ;
len -= (len % filter->channels) ;
memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
len * sizeof (filter->buffer [0])) ;
filter->b_end += len ;
filter->in_used += len ;
if (filter->in_used == filter->in_count &&
filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input)
{ /* Handle the case where all data in the current buffer has been
** consumed and this is the last buffer.
*/
if (filter->b_len - filter->b_end < half_filter_chan_len + 5)
{ /* If necessary, move data down to the start of the buffer. */
len = filter->b_end - filter->b_current ;
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
filter->b_current = half_filter_chan_len ;
filter->b_end = filter->b_current + len ;
} ;
filter->b_real_end = filter->b_end ;
len = half_filter_chan_len + 5 ;
memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ;
filter->b_end += len ;
} ;
return ;
} /* prepare_data */
static double
calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch)
{ double fraction, left, right, icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count + ch ;
left = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index + filter->channels ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;
right = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index - filter->channels ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
return (left + right) ;
} /* calc_output */

211
source/sound/SRC/src_zoh.c Normal file
View File

@ -0,0 +1,211 @@
/*
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "float_cast.h"
#include "common.h"
static int zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static void zoh_reset (SRC_PRIVATE *psrc) ;
/*========================================================================================
*/
#define ZOH_MAGIC_MARKER MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h')
typedef struct
{ int zoh_magic_marker ;
int channels ;
int reset ;
long in_count, in_used ;
long out_count, out_gen ;
float last_value [1] ;
} ZOH_DATA ;
/*----------------------------------------------------------------------------------------
*/
static int
zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ ZOH_DATA *zoh ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < zoh->channels ; ch++)
zoh->last_value [ch] = data->data_in [ch] ;
zoh->reset = 0 ;
} ;
zoh->in_count = data->input_frames * zoh->channels ;
zoh->out_count = data->output_frames * zoh->channels ;
zoh->in_used = zoh->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
input_index = psrc->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && zoh->out_gen < zoh->out_count)
{
if (zoh->in_used + zoh->channels * input_index >= zoh->in_count)
break ;
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = zoh->last_value [ch] ;
zoh->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
} ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (zoh->out_gen < zoh->out_count && zoh->in_used + zoh->channels * input_index <= zoh->in_count)
{
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = data->data_in [zoh->in_used - zoh->channels + ch] ;
zoh->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (zoh->in_used > zoh->in_count)
{ input_index += (zoh->in_used - zoh->in_count) / zoh->channels ;
zoh->in_used = zoh->in_count ;
} ;
psrc->last_position = input_index ;
if (zoh->in_used > 0)
for (ch = 0 ; ch < zoh->channels ; ch++)
zoh->last_value [ch] = data->data_in [zoh->in_used - zoh->channels + ch] ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = zoh->in_used / zoh->channels ;
data->output_frames_gen = zoh->out_gen / zoh->channels ;
return SRC_ERR_NO_ERROR ;
} /* zoh_vari_process */
/*------------------------------------------------------------------------------
*/
const char*
zoh_get_name (int src_enum)
{
if (src_enum == SRC_ZERO_ORDER_HOLD)
return "ZOH Interpolator" ;
return NULL ;
} /* zoh_get_name */
const char*
zoh_get_description (int src_enum)
{
if (src_enum == SRC_ZERO_ORDER_HOLD)
return "Zero order hold interpolator, very fast, poor quality." ;
return NULL ;
} /* zoh_get_descrition */
int
zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ ZOH_DATA *zoh = NULL ;
if (src_enum != SRC_ZERO_ORDER_HOLD)
return SRC_ERR_BAD_CONVERTER ;
if (psrc->private_data != NULL)
{ zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh->zoh_magic_marker != ZOH_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
} ;
if (psrc->private_data == NULL)
{ zoh = calloc (1, sizeof (*zoh) + psrc->channels * sizeof (float)) ;
if (zoh == NULL)
return SRC_ERR_MALLOC_FAILED ;
psrc->private_data = zoh ;
} ;
zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ;
zoh->channels = psrc->channels ;
psrc->const_process = zoh_vari_process ;
psrc->vari_process = zoh_vari_process ;
psrc->reset = zoh_reset ;
zoh_reset (psrc) ;
return SRC_ERR_NO_ERROR ;
} /* zoh_set_converter */
/*===================================================================================
*/
static void
zoh_reset (SRC_PRIVATE *psrc)
{ ZOH_DATA *zoh ;
zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh == NULL)
return ;
zoh->channels = psrc->channels ;
zoh->reset = 1 ;
memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ;
return ;
} /* zoh_reset */