~ubuntu-branches/ubuntu/gutsy/libsamplerate/gutsy

« back to all changes in this revision

Viewing changes to src/src_linear.c

  • Committer: Bazaar Package Importer
  • Author(s): Anand Kumria
  • Date: 2004-03-16 23:29:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040316232917-ivb5khznkdtkkylr
Tags: upstream-0.1.0
ImportĀ upstreamĀ versionĀ 0.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
 
3
**
 
4
** This program is free software; you can redistribute it and/or modify
 
5
** it under the terms of the GNU General Public License as published by
 
6
** the Free Software Foundation; either version 2 of the License, or
 
7
** (at your option) any later version.
 
8
**
 
9
** This program is distributed in the hope that it will be useful,
 
10
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
** GNU General Public License for more details.
 
13
**
 
14
** You should have received a copy of the GNU General Public License
 
15
** along with this program; if not, write to the Free Software
 
16
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
17
*/
 
18
 
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
 
 
23
#include "config.h"
 
24
#include "float_cast.h"
 
25
#include "common.h"
 
26
 
 
27
static void linear_reset (SRC_PRIVATE *psrc) ;
 
28
 
 
29
/*========================================================================================
 
30
*/
 
31
 
 
32
#define LINEAR_MAGIC_MARKER     MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
 
33
 
 
34
#define SRC_DEBUG       0
 
35
 
 
36
typedef struct
 
37
{       int             linear_magic_marker ;
 
38
        int             channels ;
 
39
        long    in_count, in_used ;
 
40
        long    out_count, out_gen ;
 
41
        float   last_value [1] ;
 
42
} LINEAR_DATA ;
 
43
 
 
44
/*----------------------------------------------------------------------------------------
 
45
*/
 
46
int
 
47
linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
 
48
{       LINEAR_DATA *linear ;
 
49
        double          src_ratio, input_index ;
 
50
        int                     ch ;
 
51
 
 
52
        if (psrc->private_data == NULL)
 
53
                return SRC_ERR_NO_PRIVATE ;
 
54
 
 
55
        linear = (LINEAR_DATA*) psrc->private_data ;
 
56
 
 
57
        linear->in_count = data->input_frames * linear->channels ;
 
58
        linear->out_count = data->output_frames * linear->channels ;
 
59
        linear->in_used = linear->out_gen = 0 ;
 
60
 
 
61
        src_ratio = psrc->last_ratio ;
 
62
        input_index = psrc->last_position ;
 
63
 
 
64
        /* Calculate samples before first sample in input array. */
 
65
        while (input_index < 1.0 && linear->out_gen < linear->out_count)
 
66
        {
 
67
                if (linear->in_used + linear->channels * input_index > linear->in_count)
 
68
                        break ;
 
69
 
 
70
                if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
 
71
                        src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ;
 
72
 
 
73
                for (ch = 0 ; ch < linear->channels ; ch++)
 
74
                {       data->data_out [linear->out_gen] = linear->last_value [ch] + input_index *
 
75
                                                                                (data->data_in [ch] - linear->last_value [ch]) ;
 
76
                        linear->out_gen ++ ;
 
77
                        } ;
 
78
 
 
79
                /* Figure out the next index. */
 
80
                input_index += 1.0 / src_ratio ;
 
81
                } ;
 
82
 
 
83
        linear->in_used += linear->channels * lrint (floor (input_index)) ;
 
84
        input_index -= floor (input_index) ;
 
85
 
 
86
        /* Main processing loop. */
 
87
        while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
 
88
        {
 
89
                if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
 
90
                        src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ;
 
91
 
 
92
                if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
 
93
                {       printf ("Whoops!!!!   in_used : %ld     channels : %d     input_index : %f\n", linear->in_used, linear->channels, input_index) ;
 
94
                        exit (1) ;
 
95
                        } ;
 
96
 
 
97
                for (ch = 0 ; ch < linear->channels ; ch++)
 
98
                {       data->data_out [linear->out_gen] = data->data_in [linear->in_used - linear->channels + ch] + input_index *
 
99
                                                (data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch]) ;
 
100
                        linear->out_gen ++ ;
 
101
                        } ;
 
102
 
 
103
                /* Figure out the next index. */
 
104
                input_index += 1.0 / src_ratio ;
 
105
 
 
106
                linear->in_used += linear->channels * lrint (floor (input_index)) ;
 
107
                input_index -= floor (input_index) ;
 
108
                } ;
 
109
 
 
110
        if (linear->in_used > linear->in_count)
 
111
        {       input_index += linear->in_used - linear->in_count ;
 
112
                linear->in_used = linear->in_count ;
 
113
                } ;
 
114
 
 
115
        psrc->last_position = input_index ;
 
116
 
 
117
        if (linear->in_used > 0)
 
118
                for (ch = 0 ; ch < linear->channels ; ch++)
 
119
                        linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ;
 
120
 
 
121
        /* Save current ratio rather then target ratio. */
 
122
        psrc->last_ratio = src_ratio ;
 
123
 
 
124
        data->input_frames_used = linear->in_used / linear->channels ;
 
125
        data->output_frames_gen = linear->out_gen / linear->channels ;
 
126
 
 
127
        return SRC_ERR_NO_ERROR ;
 
128
} /* linear_process */
 
129
 
 
130
/*------------------------------------------------------------------------------
 
131
*/
 
132
 
 
133
const char*
 
134
linear_get_name (int src_enum)
 
135
{
 
136
        if (src_enum == SRC_LINEAR)
 
137
                return "Linear Interpolator" ;
 
138
 
 
139
        return NULL ;
 
140
} /* linear_get_name */
 
141
 
 
142
const char*
 
143
linear_get_description (int src_enum)
 
144
{
 
145
        if (src_enum == SRC_LINEAR)
 
146
                return "Linear interpolator, very fast, poor quality." ;
 
147
 
 
148
        return NULL ;
 
149
} /* linear_get_descrition */
 
150
 
 
151
int
 
152
linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
 
153
{       LINEAR_DATA *linear = NULL ;
 
154
 
 
155
        if (src_enum != SRC_LINEAR)
 
156
                return SRC_ERR_BAD_CONVERTER ;
 
157
 
 
158
        if (psrc->private_data != NULL)
 
159
        {       linear = (LINEAR_DATA*) psrc->private_data ;
 
160
                if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER)
 
161
                {       free (psrc->private_data) ;
 
162
                        psrc->private_data = NULL ;
 
163
                        } ;
 
164
                } ;
 
165
 
 
166
        if (psrc->private_data == NULL)
 
167
        {       linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ;
 
168
                if (linear == NULL)
 
169
                        return SRC_ERR_MALLOC_FAILED ;
 
170
                psrc->private_data = linear ;
 
171
                } ;
 
172
 
 
173
        linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
 
174
        linear->channels = psrc->channels ;
 
175
 
 
176
        psrc->process = linear_process ;
 
177
        psrc->reset = linear_reset ;
 
178
 
 
179
        linear_reset (psrc) ;
 
180
 
 
181
        return SRC_ERR_NO_ERROR ;
 
182
} /* linear_set_converter */
 
183
 
 
184
/*===================================================================================
 
185
*/
 
186
 
 
187
static void
 
188
linear_reset (SRC_PRIVATE *psrc)
 
189
{       LINEAR_DATA *linear = NULL ;
 
190
 
 
191
        linear = (LINEAR_DATA*) psrc->private_data ;
 
192
        if (linear == NULL)
 
193
                return ;
 
194
 
 
195
        memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
 
196
} /* linear_reset */
 
197
/*
 
198
** Do not edit or modify anything in this comment block.
 
199
** The arch-tag line is a file identity tag for the GNU Arch 
 
200
** revision control system.
 
201
**
 
202
** arch-tag: 7eac3103-3d84-45d3-8bbd-f409c2b2d1a9
 
203
*/
 
204