1*9484Sgarrett.damore@Sun.COM /* 2*9484Sgarrett.damore@Sun.COM * CDDL HEADER START 3*9484Sgarrett.damore@Sun.COM * 4*9484Sgarrett.damore@Sun.COM * The contents of this file are subject to the terms of the 5*9484Sgarrett.damore@Sun.COM * Common Development and Distribution License (the "License"). 6*9484Sgarrett.damore@Sun.COM * You may not use this file except in compliance with the License. 7*9484Sgarrett.damore@Sun.COM * 8*9484Sgarrett.damore@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9484Sgarrett.damore@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*9484Sgarrett.damore@Sun.COM * See the License for the specific language governing permissions 11*9484Sgarrett.damore@Sun.COM * and limitations under the License. 12*9484Sgarrett.damore@Sun.COM * 13*9484Sgarrett.damore@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*9484Sgarrett.damore@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9484Sgarrett.damore@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*9484Sgarrett.damore@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*9484Sgarrett.damore@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*9484Sgarrett.damore@Sun.COM * 19*9484Sgarrett.damore@Sun.COM * CDDL HEADER END 20*9484Sgarrett.damore@Sun.COM */ 21*9484Sgarrett.damore@Sun.COM /* 22*9484Sgarrett.damore@Sun.COM * Copyright (C) 4Front Technologies 1996-2008. 23*9484Sgarrett.damore@Sun.COM * 24*9484Sgarrett.damore@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25*9484Sgarrett.damore@Sun.COM * Use is subject to license terms. 26*9484Sgarrett.damore@Sun.COM */ 27*9484Sgarrett.damore@Sun.COM 28*9484Sgarrett.damore@Sun.COM /* 29*9484Sgarrett.damore@Sun.COM * Purpose: GRC library version 3.1 internal definitions 30*9484Sgarrett.damore@Sun.COM * 31*9484Sgarrett.damore@Sun.COM * GRC3 is a high quality sample rate conversion module that uses fixed point 32*9484Sgarrett.damore@Sun.COM * arithmetic. 33*9484Sgarrett.damore@Sun.COM */ 34*9484Sgarrett.damore@Sun.COM 35*9484Sgarrett.damore@Sun.COM #ifndef AUDIO_GRC3_H 36*9484Sgarrett.damore@Sun.COM #define AUDIO_GRC3_H 37*9484Sgarrett.damore@Sun.COM 38*9484Sgarrett.damore@Sun.COM #define GRC3_MAXHISTORY 4096 39*9484Sgarrett.damore@Sun.COM 40*9484Sgarrett.damore@Sun.COM #ifdef __cplusplus 41*9484Sgarrett.damore@Sun.COM extern "C" 42*9484Sgarrett.damore@Sun.COM { 43*9484Sgarrett.damore@Sun.COM #endif 44*9484Sgarrett.damore@Sun.COM 45*9484Sgarrett.damore@Sun.COM typedef struct grc3state { 46*9484Sgarrett.damore@Sun.COM uint32_t srcrate; 47*9484Sgarrett.damore@Sun.COM uint32_t dstrate; 48*9484Sgarrett.damore@Sun.COM uint32_t ptr; 49*9484Sgarrett.damore@Sun.COM uint32_t ptr_incv; 50*9484Sgarrett.damore@Sun.COM 51*9484Sgarrett.damore@Sun.COM uint32_t sat; 52*9484Sgarrett.damore@Sun.COM uint32_t filtfactor; 53*9484Sgarrett.damore@Sun.COM int32_t *historyptr; 54*9484Sgarrett.damore@Sun.COM int32_t dummy_pad1; 55*9484Sgarrett.damore@Sun.COM 56*9484Sgarrett.damore@Sun.COM int32_t history[GRC3_MAXHISTORY * 2]; 57*9484Sgarrett.damore@Sun.COM 58*9484Sgarrett.damore@Sun.COM uint32_t outsz; 59*9484Sgarrett.damore@Sun.COM } grc3state_t; 60*9484Sgarrett.damore@Sun.COM 61*9484Sgarrett.damore@Sun.COM 62*9484Sgarrett.damore@Sun.COM /* BEGIN CSTYLED */ 63*9484Sgarrett.damore@Sun.COM /***************************************************************************** 64*9484Sgarrett.damore@Sun.COM 65*9484Sgarrett.damore@Sun.COM Tutorial on how to use GRC3 rate conversion 66*9484Sgarrett.damore@Sun.COM 67*9484Sgarrett.damore@Sun.COM 1. First, you create an instance of grc3state_t for each channel. If you 68*9484Sgarrett.damore@Sun.COM are working with stereo files - you will need 2 of such instances, 69*9484Sgarrett.damore@Sun.COM for quadro - 4. 70*9484Sgarrett.damore@Sun.COM 71*9484Sgarrett.damore@Sun.COM The instances may be allocated in either static or dynamic memory - that 72*9484Sgarrett.damore@Sun.COM makes no difference to the convertor. So, if your program has to process 73*9484Sgarrett.damore@Sun.COM one stereo stream, there's no reason why should you use malloc/free to 74*9484Sgarrett.damore@Sun.COM allocate/deallocate structures. Also, in device drivers, you can 75*9484Sgarrett.damore@Sun.COM use static variables as well: 76*9484Sgarrett.damore@Sun.COM 77*9484Sgarrett.damore@Sun.COM static grc3state_t grc[2]; // for two channels 78*9484Sgarrett.damore@Sun.COM 79*9484Sgarrett.damore@Sun.COM 80*9484Sgarrett.damore@Sun.COM 2. Before starting any conversion, grc3state_t instances should be initialized 81*9484Sgarrett.damore@Sun.COM properly, and you do this with grc3_setup function. Function itself does 82*9484Sgarrett.damore@Sun.COM not allocate additional memory or change anything except grc3state_t 83*9484Sgarrett.damore@Sun.COM structure, so this is thread safe, and you don't have to do additional 84*9484Sgarrett.damore@Sun.COM "deinitialization". 85*9484Sgarrett.damore@Sun.COM 86*9484Sgarrett.damore@Sun.COM If you are doing interleaved audio (stereo/quadro/whatever) conversion, 87*9484Sgarrett.damore@Sun.COM you should do setup on each of the channels, and should have separate 88*9484Sgarrett.damore@Sun.COM instance of grc3state_t for each channel. As you will understand further, 89*9484Sgarrett.damore@Sun.COM such conversion is done separately. And now, the setup function: 90*9484Sgarrett.damore@Sun.COM 91*9484Sgarrett.damore@Sun.COM int grc3_setup( grc3state_t *grc, 92*9484Sgarrett.damore@Sun.COM uint32_t fromRate, 93*9484Sgarrett.damore@Sun.COM uint32_t toRate ); 94*9484Sgarrett.damore@Sun.COM 95*9484Sgarrett.damore@Sun.COM grc - pointer to grc3state_t instance 96*9484Sgarrett.damore@Sun.COM fromRate - source sample rate 97*9484Sgarrett.damore@Sun.COM toRate - destination sample rate 98*9484Sgarrett.damore@Sun.COM 99*9484Sgarrett.damore@Sun.COM Note, that sample rates itself are not important - the important thing 100*9484Sgarrett.damore@Sun.COM is ratio between those sample rates. So, for example, if you have to 101*9484Sgarrett.damore@Sun.COM convert from 24000Hz to 48000Hz, it's ok to write: 102*9484Sgarrett.damore@Sun.COM 103*9484Sgarrett.damore@Sun.COM grc3_setup( &grc[0], 240, 480 ); 104*9484Sgarrett.damore@Sun.COM 105*9484Sgarrett.damore@Sun.COM Sometimes (in MIDI synths) it would be desired to use fractional sample 106*9484Sgarrett.damore@Sun.COM rates. For example, setup for conversion from 33100.78 to 48000 may look 107*9484Sgarrett.damore@Sun.COM like this: 108*9484Sgarrett.damore@Sun.COM 109*9484Sgarrett.damore@Sun.COM grc3_setup( &grc[0], 3310078, 4800000); 110*9484Sgarrett.damore@Sun.COM 111*9484Sgarrett.damore@Sun.COM Note, that on stereo, GRC3 setup will look like this: 112*9484Sgarrett.damore@Sun.COM 113*9484Sgarrett.damore@Sun.COM static grc3state_t grc[2]; 114*9484Sgarrett.damore@Sun.COM 115*9484Sgarrett.damore@Sun.COM // ... 116*9484Sgarrett.damore@Sun.COM 117*9484Sgarrett.damore@Sun.COM grc3_setup( &grc[0], 3310078, 4800000) 118*9484Sgarrett.damore@Sun.COM grc3_setup( &grc[1], 3310078, 4800000); 119*9484Sgarrett.damore@Sun.COM 120*9484Sgarrett.damore@Sun.COM 121*9484Sgarrett.damore@Sun.COM Note, that you should not rely on grc3_setup's fast execution or any 122*9484Sgarrett.damore@Sun.COM execution timing. It may contain some massive arithmetic and even huge 123*9484Sgarrett.damore@Sun.COM loops, so avoid putting grc3_setup to inner loops and calling in 124*9484Sgarrett.damore@Sun.COM latency-dependent code. 125*9484Sgarrett.damore@Sun.COM 126*9484Sgarrett.damore@Sun.COM 127*9484Sgarrett.damore@Sun.COM 3. Next, before running a stream through grc3_convert function, you should 128*9484Sgarrett.damore@Sun.COM reset each of grc3state_t instance used: 129*9484Sgarrett.damore@Sun.COM 130*9484Sgarrett.damore@Sun.COM void grc3_reset(grc3state_t *grc); 131*9484Sgarrett.damore@Sun.COM 132*9484Sgarrett.damore@Sun.COM 133*9484Sgarrett.damore@Sun.COM grc - pointer to GRC3 instance variable 134*9484Sgarrett.damore@Sun.COM 135*9484Sgarrett.damore@Sun.COM So, for stereo, this appears to be: 136*9484Sgarrett.damore@Sun.COM 137*9484Sgarrett.damore@Sun.COM static grc3state_t grc[2]; 138*9484Sgarrett.damore@Sun.COM 139*9484Sgarrett.damore@Sun.COM // ... 140*9484Sgarrett.damore@Sun.COM 141*9484Sgarrett.damore@Sun.COM grc3_reset( &grc[0] ); 142*9484Sgarrett.damore@Sun.COM grc3_reset( &grc[1] ); 143*9484Sgarrett.damore@Sun.COM 144*9484Sgarrett.damore@Sun.COM 145*9484Sgarrett.damore@Sun.COM 4. Finally, doing conversion is easy: 146*9484Sgarrett.damore@Sun.COM 147*9484Sgarrett.damore@Sun.COM void grc3_convert( grc3state_t *grc, 148*9484Sgarrett.damore@Sun.COM int domain, 149*9484Sgarrett.damore@Sun.COM int quality, 150*9484Sgarrett.damore@Sun.COM const void *src, 151*9484Sgarrett.damore@Sun.COM void *dst, 152*9484Sgarrett.damore@Sun.COM int maxInSize, 153*9484Sgarrett.damore@Sun.COM int maxOutSize, 154*9484Sgarrett.damore@Sun.COM int interleave, 155*9484Sgarrett.damore@Sun.COM int offset ); 156*9484Sgarrett.damore@Sun.COM 157*9484Sgarrett.damore@Sun.COM 158*9484Sgarrett.damore@Sun.COM grc - pointer to initialized grc3state_t instance; you 159*9484Sgarrett.damore@Sun.COM can specify NULL to check whether a particular 160*9484Sgarrett.damore@Sun.COM domain/quality pair is supported, check return value 161*9484Sgarrett.damore@Sun.COM 162*9484Sgarrett.damore@Sun.COM quality - quality to use for conversion, supported values are: 163*9484Sgarrett.damore@Sun.COM 164*9484Sgarrett.damore@Sun.COM 0 - D lowest quality (normally equals to low quality) 165*9484Sgarrett.damore@Sun.COM 1 - L low quality (spline interpolation) 166*9484Sgarrett.damore@Sun.COM 2 - M medium quality (lagrange interpolation) 167*9484Sgarrett.damore@Sun.COM 3 - H high quality 168*9484Sgarrett.damore@Sun.COM 4 - HX high quality (high quality with extra precision) 169*9484Sgarrett.damore@Sun.COM 5 - P production quality 170*9484Sgarrett.damore@Sun.COM 171*9484Sgarrett.damore@Sun.COM 6 - PX production quality (prod quality with extra precision) 172*9484Sgarrett.damore@Sun.COM (PX is currently disabled because it causes a crash) 173*9484Sgarrett.damore@Sun.COM 174*9484Sgarrett.damore@Sun.COM src - source audio buffer 175*9484Sgarrett.damore@Sun.COM 176*9484Sgarrett.damore@Sun.COM dst - destination audio buffer; 177*9484Sgarrett.damore@Sun.COM 178*9484Sgarrett.damore@Sun.COM maxInSize - size of input buffer (in samples per channel!) 179*9484Sgarrett.damore@Sun.COM 180*9484Sgarrett.damore@Sun.COM maxOutSize - size of output buffer (in samples per channel!) 181*9484Sgarrett.damore@Sun.COM (will never overrun this size) 182*9484Sgarrett.damore@Sun.COM 183*9484Sgarrett.damore@Sun.COM interleave - interleave factor; for MONO or non-interleaved data 184*9484Sgarrett.damore@Sun.COM it should be equal to 1; 185*9484Sgarrett.damore@Sun.COM 186*9484Sgarrett.damore@Sun.COM 2 - STEREO interleaved audio 187*9484Sgarrett.damore@Sun.COM 4 - QUADRO interleaved audio 188*9484Sgarrett.damore@Sun.COM 189*9484Sgarrett.damore@Sun.COM So, basically, this parameter should be equal to number 190*9484Sgarrett.damore@Sun.COM of interleaved channels 191*9484Sgarrett.damore@Sun.COM 192*9484Sgarrett.damore@Sun.COM offset - number of interleaved channel currently processing, 193*9484Sgarrett.damore@Sun.COM starting from 0; for MONO or non-interleaved data 194*9484Sgarrett.damore@Sun.COM it should be equal to 0 195*9484Sgarrett.damore@Sun.COM 196*9484Sgarrett.damore@Sun.COM 197*9484Sgarrett.damore@Sun.COM For unsupported quality values, it will fall back to 198*9484Sgarrett.damore@Sun.COM "D" quality (the lowest one) 199*9484Sgarrett.damore@Sun.COM 200*9484Sgarrett.damore@Sun.COM also on return it sets: 201*9484Sgarrett.damore@Sun.COM 202*9484Sgarrett.damore@Sun.COM grc->outsz == number of output samples 203*9484Sgarrett.damore@Sun.COM 204*9484Sgarrett.damore@Sun.COM Note, that if quality is not supported, 205*9484Sgarrett.damore@Sun.COM calling the function with real data will fall back 206*9484Sgarrett.damore@Sun.COM to the worst quality available. 207*9484Sgarrett.damore@Sun.COM 208*9484Sgarrett.damore@Sun.COM Note that this version of GRC3 only supports 24-bit 209*9484Sgarrett.damore@Sun.COM native endian. (Modified by Sun for performance.) 210*9484Sgarrett.damore@Sun.COM 211*9484Sgarrett.damore@Sun.COM 212*9484Sgarrett.damore@Sun.COM 213*9484Sgarrett.damore@Sun.COM 5. Interleaved processing of N channels is done like this: 214*9484Sgarrett.damore@Sun.COM 215*9484Sgarrett.damore@Sun.COM 216*9484Sgarrett.damore@Sun.COM static grc3state_t grc[N]; 217*9484Sgarrett.damore@Sun.COM int t; 218*9484Sgarrett.damore@Sun.COM 219*9484Sgarrett.damore@Sun.COM //... 220*9484Sgarrett.damore@Sun.COM 221*9484Sgarrett.damore@Sun.COM 222*9484Sgarrett.damore@Sun.COM for(t=0; t<N; t++) 223*9484Sgarrett.damore@Sun.COM { 224*9484Sgarrett.damore@Sun.COM grc3_setup( &grc[t], 22050, 48000 ); 225*9484Sgarrett.damore@Sun.COM 226*9484Sgarrett.damore@Sun.COM grc3_reset( &grc[t] ); 227*9484Sgarrett.damore@Sun.COM } 228*9484Sgarrett.damore@Sun.COM 229*9484Sgarrett.damore@Sun.COM 230*9484Sgarrett.damore@Sun.COM //... 231*9484Sgarrett.damore@Sun.COM 232*9484Sgarrett.damore@Sun.COM while (...) { 233*9484Sgarrett.damore@Sun.COM 234*9484Sgarrett.damore@Sun.COM for(t = 0; t < N; t++) { 235*9484Sgarrett.damore@Sun.COM grc3_convert(&grc[t], // instance pointer 236*9484Sgarrett.damore@Sun.COM 4, // quality 237*9484Sgarrett.damore@Sun.COM in_buffer, // input buffer 238*9484Sgarrett.damore@Sun.COM out_buffer, // input buffer 239*9484Sgarrett.damore@Sun.COM in_samples_count, // number of samples 240*9484Sgarrett.damore@Sun.COM // in in_buffer 241*9484Sgarrett.damore@Sun.COM 2048, // size of out_buffer 242*9484Sgarrett.damore@Sun.COM N, t // num of channels, channel# 243*9484Sgarrett.damore@Sun.COM ); 244*9484Sgarrett.damore@Sun.COM } 245*9484Sgarrett.damore@Sun.COM 246*9484Sgarrett.damore@Sun.COM 247*9484Sgarrett.damore@Sun.COM // Normally, for interleaved data, ->outsz of all instances will 248*9484Sgarrett.damore@Sun.COM // be the same for the same stream 249*9484Sgarrett.damore@Sun.COM 250*9484Sgarrett.damore@Sun.COM put_sound_somewhere(out_buffer, 251*9484Sgarrett.damore@Sun.COM grc[0]->outsz * N * sizeof(out_buffer[0]) ); 252*9484Sgarrett.damore@Sun.COM } 253*9484Sgarrett.damore@Sun.COM 254*9484Sgarrett.damore@Sun.COM 255*9484Sgarrett.damore@Sun.COM 6. If you use the same storage and the same setup for processing few separate 256*9484Sgarrett.damore@Sun.COM non-related sounds, to prevent the feedback of sound1's tail to sound2's 257*9484Sgarrett.damore@Sun.COM beginning - do grc3_reset on the state instances before calling 258*9484Sgarrett.damore@Sun.COM grc_convert. 259*9484Sgarrett.damore@Sun.COM 260*9484Sgarrett.damore@Sun.COM ***************************************************************************** 261*9484Sgarrett.damore@Sun.COM */ 262*9484Sgarrett.damore@Sun.COM /* END CSTYLED */ 263*9484Sgarrett.damore@Sun.COM 264*9484Sgarrett.damore@Sun.COM void grc3_setup(grc3state_t *, uint32_t fromRate, uint32_t toRate); 265*9484Sgarrett.damore@Sun.COM 266*9484Sgarrett.damore@Sun.COM void grc3_reset(grc3state_t *); 267*9484Sgarrett.damore@Sun.COM 268*9484Sgarrett.damore@Sun.COM void grc3_convert(grc3state_t *, int quality, 269*9484Sgarrett.damore@Sun.COM const void *src, void *dst, int sz, int bufsz, int inc, int offset); 270*9484Sgarrett.damore@Sun.COM 271*9484Sgarrett.damore@Sun.COM #ifdef __cplusplus 272*9484Sgarrett.damore@Sun.COM }; 273*9484Sgarrett.damore@Sun.COM #endif 274*9484Sgarrett.damore@Sun.COM 275*9484Sgarrett.damore@Sun.COM #endif /* AUDIO_GRC3_H */ 276