88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER START
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The contents of this file are subject to the terms of the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common Development and Distribution License (the "License").
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You may not use this file except in compliance with the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the License for the specific language governing permissions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and limitations under the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER END
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Copyright (C) 4Front Technologies 1996-2008.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Use is subject to license terms.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Purpose: GRC library version 3.1 internal definitions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * GRC3 is a high quality sample rate conversion module that uses fixed point
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * arithmetic.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* BEGIN CSTYLED */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*****************************************************************************
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Tutorial on how to use GRC3 rate conversion
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore1. First, you create an instance of grc3state_t for each channel. If you
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore are working with stereo files - you will need 2 of such instances,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for quadro - 4.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore The instances may be allocated in either static or dynamic memory - that
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore makes no difference to the convertor. So, if your program has to process
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore one stereo stream, there's no reason why should you use malloc/free to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore allocate/deallocate structures. Also, in device drivers, you can
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore use static variables as well:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore static grc3state_t grc[2]; // for two channels
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore2. Before starting any conversion, grc3state_t instances should be initialized
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore properly, and you do this with grc3_setup function. Function itself does
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore not allocate additional memory or change anything except grc3state_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore structure, so this is thread safe, and you don't have to do additional
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "deinitialization".
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore If you are doing interleaved audio (stereo/quadro/whatever) conversion,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore you should do setup on each of the channels, and should have separate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore instance of grc3state_t for each channel. As you will understand further,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore such conversion is done separately. And now, the setup function:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int grc3_setup( grc3state_t *grc,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t fromRate,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t toRate );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc - pointer to grc3state_t instance
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fromRate - source sample rate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore toRate - destination sample rate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Note, that sample rates itself are not important - the important thing
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore is ratio between those sample rates. So, for example, if you have to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore convert from 24000Hz to 48000Hz, it's ok to write:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup( &grc[0], 240, 480 );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Sometimes (in MIDI synths) it would be desired to use fractional sample
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rates. For example, setup for conversion from 33100.78 to 48000 may look
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup( &grc[0], 3310078, 4800000);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Note, that on stereo, GRC3 setup will look like this:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore static grc3state_t grc[2];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup( &grc[0], 3310078, 4800000)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup( &grc[1], 3310078, 4800000);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Note, that you should not rely on grc3_setup's fast execution or any
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore execution timing. It may contain some massive arithmetic and even huge
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore loops, so avoid putting grc3_setup to inner loops and calling in
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore latency-dependent code.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore3. Next, before running a stream through grc3_convert function, you should
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore reset each of grc3state_t instance used:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void grc3_reset(grc3state_t *grc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc - pointer to GRC3 instance variable
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore So, for stereo, this appears to be:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore static grc3state_t grc[2];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_reset( &grc[0] );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_reset( &grc[1] );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore4. Finally, doing conversion is easy:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void grc3_convert( grc3state_t *grc,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const void *src,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int maxInSize,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int maxOutSize,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int interleave,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int offset );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc - pointer to initialized grc3state_t instance; you
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore can specify NULL to check whether a particular
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore domain/quality pair is supported, check return value
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore quality - quality to use for conversion, supported values are:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 - D lowest quality (normally equals to low quality)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 1 - L low quality (spline interpolation)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 2 - M medium quality (lagrange interpolation)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 3 - H high quality
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4 - HX high quality (high quality with extra precision)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 5 - P production quality
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 6 - PX production quality (prod quality with extra precision)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (PX is currently disabled because it causes a crash)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore src - source audio buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dst - destination audio buffer;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore maxInSize - size of input buffer (in samples per channel!)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore maxOutSize - size of output buffer (in samples per channel!)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (will never overrun this size)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore interleave - interleave factor; for MONO or non-interleaved data
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore it should be equal to 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 2 - STEREO interleaved audio
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4 - QUADRO interleaved audio
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore So, basically, this parameter should be equal to number
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore of interleaved channels
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore offset - number of interleaved channel currently processing,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore starting from 0; for MONO or non-interleaved data
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore it should be equal to 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore For unsupported quality values, it will fall back to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "D" quality (the lowest one)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore also on return it sets:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc->outsz == number of output samples
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Note, that if quality is not supported,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore calling the function with real data will fall back
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore to the worst quality available.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore Note that this version of GRC3 only supports 24-bit
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore native endian. (Modified by Sun for performance.)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore5. Interleaved processing of N channels is done like this:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore static grc3state_t grc[N];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for(t=0; t<N; t++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup( &grc[t], 22050, 48000 );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_reset( &grc[t] );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore while (...) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for(t = 0; t < N; t++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_convert(&grc[t], // instance pointer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4, // quality
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore in_buffer, // input buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore out_buffer, // input buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore in_samples_count, // number of samples
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore // in in_buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 2048, // size of out_buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore N, t // num of channels, channel#
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore // Normally, for interleaved data, ->outsz of all instances will
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore // be the same for the same stream
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore put_sound_somewhere(out_buffer,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc[0]->outsz * N * sizeof(out_buffer[0]) );
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore6. If you use the same storage and the same setup for processing few separate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore non-related sounds, to prevent the feedback of sound1's tail to sound2's
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore beginning - do grc3_reset on the state instances before calling
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore*****************************************************************************
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* END CSTYLED */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid grc3_setup(grc3state_t *, uint32_t fromRate, uint32_t toRate);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid grc3_convert(grc3state_t *, int quality,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const void *src, void *dst, int sz, int bufsz, int inc, int offset);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif /* AUDIO_GRC3_H */