~ubuntu-branches/ubuntu/feisty/avidemux/feisty

« back to all changes in this revision

Viewing changes to avidemux/ADM_audiofilter/audioeng_6dbpress.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-12-15 17:13:20 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20061215171320-w79pvpehxx2fr217
Tags: 1:2.3.0-0.0ubuntu1
* Merge from debian-multimedia.org, remaining Ubuntu change:
  - desktop file,
  - no support for ccache and make -j.
* Closes Ubuntu: #69614.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
                          audioeng_6dbpress.cpp  -  description
3
 
                             -------------------
4
 
        Derived from audactity compressor
5
 
        see http://audacity.sf.net
6
 
 ***************************************************************************/
7
 
/**********************************************************************
8
 
 
9
 
  Audacity: A Digital Audio Editor
10
 
 
11
 
  Compressor.cpp
12
 
 
13
 
  Dominic Mazzoni
14
 
 
15
 
  Steve Jolly made it inherit from EffectSimpleMono.
16
 
  GUI added and implementation improved by Dominic Mazzoni, 5/11/2003.
17
 
 
18
 
**********************************************************************/
19
 
 
20
 
 
21
 
/***************************************************************************
22
 
 *                                                                         *
23
 
 *   This program is free software; you can redistribute it and/or modify  *
24
 
 *   it under the terms of the GNU General Public License as published by  *
25
 
 *   the Free Software Foundation; either version 2 of the License, or     *
26
 
 *   (at your option) any later version.                                   *
27
 
 *                                                                         *
28
 
 ***************************************************************************/
29
 
#include <stdio.h>
30
 
#include <stdlib.h>
31
 
#include <string.h>
32
 
//#include <stream.h>
33
 
#include <ADM_assert.h>
34
 
#include <math.h>
35
 
 
36
 
#include "config.h"
37
 
#include "avifmt.h"
38
 
#include "avifmt2.h"
39
 
#include "avio.hxx"
40
 
#include "fourcc.h"
41
 
//#include "aviaudio.hxx"
42
 
#include "audioprocess.hxx"
43
 
//#include "../toolkit.hxx"
44
 
// Ctor
45
 
//__________
46
 
 
47
 
 
48
 
AVDMProcessAudio_Compress::AVDMProcessAudio_Compress(AVDMGenericAudioStream * instream,DRCparam *p):AVDMBufferedAudioStream
49
 
    (instream)
50
 
{
51
 
#define AMP 4
52
 
    // nothing special here...
53
 
    double ramp, coef, off;
54
 
 
55
 
    _wavheader = new WAVHeader;
56
 
 
57
 
    memcpy(_wavheader, _instream->getInfo(), sizeof(WAVHeader));
58
 
    _wavheader->encoding = WAV_PCM;
59
 
    _wavheader->byterate =
60
 
        _wavheader->channels * _wavheader->frequency * 2;
61
 
    _instream->goToTime(0);
62
 
    memcpy(&_param,p,sizeof(_param));
63
 
//
64
 
// The base is 100 ms
65
 
//
66
 
 
67
 
    strcpy(_name, "PROC:PRESS");
68
 
    mCircleSize=DRC_WINDOW;
69
 
    drc_cleanup();
70
 
   
71
 
 
72
 
 
73
 
};
74
 
void AVDMProcessAudio_Compress::drc_cleanup(void)
75
 
{
76
 
    double mCurRate=(double)_wavheader->frequency;
77
 
    
78
 
    
79
 
   for(int j=0; j<mCircleSize; j++) {
80
 
      mCircle[j] = 0.0;
81
 
      mLevelCircle[j] = _param.mFloor;
82
 
   }
83
 
   mCirclePos = 0;
84
 
   mRMSSum = 0.0;
85
 
 
86
 
   mGainDB = ((_param.mThresholdDB*-0.7) * (1 - 1/_param.mRatio));
87
 
   if (mGainDB < 0)
88
 
      mGainDB = 0;
89
 
 
90
 
   mThreshold = pow(10.0, _param.mThresholdDB/10); // factor of 10 because it's power
91
 
 
92
 
   if (_param.mUseGain)
93
 
      mGain = pow(10.0, mGainDB/20); // factor of 20 because it's amplitude
94
 
   else
95
 
      mGain = 1.0;
96
 
 
97
 
   mAttackFactor = exp(-log(_param.mFloor) / (mCurRate * _param.mAttackTime + 0.5));
98
 
   mDecayFactor = exp(log(_param.mFloor) / (mCurRate * _param.mDecayTime + 0.5));
99
 
 
100
 
   mLastLevel = 0.0;
101
 
   
102
 
   memset(mCircle,0,sizeof(mCircle));
103
 
   memset(follow,0,sizeof(follow));
104
 
   memset(mLevelCircle,0,sizeof(mLevelCircle));
105
 
    
106
 
}
107
 
//
108
 
AVDMProcessAudio_Compress::~AVDMProcessAudio_Compress()
109
 
{
110
 
        delete _wavheader;
111
 
}
112
 
 
113
 
 
114
 
//_____________________________________________
115
 
uint32_t AVDMProcessAudio_Compress::grab(uint8_t * _outbuff)
116
 
{
117
 
 
118
 
 
119
 
    int len = 0,i;
120
 
    uint8_t *incoming=(uint8_t *)_buffer;
121
 
 
122
 
    len = _instream->read(ONE_CHUNK, (uint8_t *) (incoming));
123
 
    //printf("\n grabbing :%lu-->%lu\n",ms100,rdall);               
124
 
    // Block not filled
125
 
    if (len != ONE_CHUNK)
126
 
      {
127
 
          printf("\n not enough...\n");
128
 
          if (len == 0)
129
 
              return MINUS_ONE; // we could not get a single byte ! End of stream
130
 
          // Else fillout with 0
131
 
          for(int i=len;i<ONE_CHUNK;i++)
132
 
                incoming[i]=0;
133
 
      }
134
 
      // Convert to float between 1&-1
135
 
      for(i=0;i<ONE_CHUNK/2;i++)
136
 
      {
137
 
        value[i]=(double)_buffer[i]/32767.;   
138
 
      }
139
 
    /*******/
140
 
   
141
 
    int16_t *ofer=(int16_t *)_outbuff;     // Out
142
 
    len=ONE_CHUNK/2;// 16 bits / sample
143
 
    
144
 
    
145
 
    if (mLastLevel == 0.0) {
146
 
      int preSeed = mCircleSize;
147
 
      if (preSeed > len)
148
 
         preSeed = len;
149
 
      for(i=0; i<preSeed; i++)
150
 
         AvgCircle(value[i]);
151
 
   }
152
 
 
153
 
   for (i = 0; i < len; i++) {
154
 
      Follow(value[i], &follow[i], i);
155
 
   }
156
 
 
157
 
   for (i = 0; i < len; i++) {
158
 
      ofer[i] =(int16_t) (32767.*DoCompression(value[i], follow[i]));
159
 
   }  
160
 
   
161
 
    return len*2;
162
 
 
163
 
}
164
 
double AVDMProcessAudio_Compress::AvgCircle(double value)
165
 
{
166
 
   double level;
167
 
 
168
 
   // Calculate current level from root-mean-squared of
169
 
   // circular buffer ("RMS")
170
 
   mRMSSum -= mCircle[mCirclePos];
171
 
   mCircle[mCirclePos] = value*value;
172
 
   mRMSSum += mCircle[mCirclePos];
173
 
   level = sqrt(mRMSSum/mCircleSize);
174
 
   mLevelCircle[mCirclePos] = level;
175
 
   mCirclePos = (mCirclePos+1)%mCircleSize;  
176
 
   return level;
177
 
}
178
 
 
179
 
void AVDMProcessAudio_Compress::Follow(double x, double *outEnv, int maxBack)
180
 
{
181
 
   /*
182
 
 
183
 
   "Follow"ing algorithm by Roger B. Dannenberg, taken from
184
 
   Nyquist.  His description follows.  -DMM
185
 
 
186
 
   Description: this is a sophisticated envelope follower.
187
 
    The input is an envelope, e.g. something produced with
188
 
    the AVG function. The purpose of this function is to
189
 
    generate a smooth envelope that is generally not less
190
 
    than the input signal. In other words, we want to "ride"
191
 
    the peaks of the signal with a smooth function. The 
192
 
    algorithm is as follows: keep a current output value
193
 
    (called the "value"). The value is allowed to increase
194
 
    by at most rise_factor and decrease by at most fall_factor.
195
 
    Therefore, the next value should be between
196
 
    value * rise_factor and value * fall_factor. If the input
197
 
    is in this range, then the next value is simply the input.
198
 
    If the input is less than value * fall_factor, then the
199
 
    next value is just value * fall_factor, which will be greater
200
 
    than the input signal. If the input is greater than value *
201
 
    rise_factor, then we compute a rising envelope that meets
202
 
    the input value by working bacwards in time, changing the
203
 
    previous values to input / rise_factor, input / rise_factor^2,
204
 
    input / rise_factor^3, etc. until this new envelope intersects
205
 
    the previously computed values. There is only a limited buffer
206
 
    in which we can work backwards, so if the new envelope does not
207
 
    intersect the old one, then make yet another pass, this time
208
 
    from the oldest buffered value forward, increasing on each 
209
 
    sample by rise_factor to produce a maximal envelope. This will 
210
 
    still be less than the input.
211
 
    
212
 
    The value has a lower limit of floor to make sure value has a 
213
 
    reasonable positive value from which to begin an attack.
214
 
   */
215
 
 
216
 
   float level = AvgCircle(x);
217
 
   float high = mLastLevel * mAttackFactor;
218
 
   float low = mLastLevel * mDecayFactor;
219
 
 
220
 
   if (low < _param.mFloor)
221
 
      low = _param.mFloor;
222
 
 
223
 
   if (level < low)
224
 
      *outEnv = low;
225
 
   else if (level < high)
226
 
      *outEnv = level;
227
 
   else {
228
 
      // Backtrack
229
 
      double attackInverse = 1.0 / mAttackFactor;
230
 
      double temp = level * attackInverse;
231
 
 
232
 
      int backtrack = 50;
233
 
      if (backtrack > maxBack)
234
 
         backtrack = maxBack;
235
 
 
236
 
      double *ptr = &outEnv[-1];
237
 
      int i;
238
 
      bool ok = false;
239
 
      for(i=0; i<backtrack-2; i++) {
240
 
         if (*ptr < temp) {
241
 
            *ptr-- = temp;
242
 
            temp *= attackInverse;
243
 
         }
244
 
         else {
245
 
            ok = true;
246
 
            break;
247
 
         }   
248
 
      }
249
 
 
250
 
      if (!ok && backtrack>1 && (*ptr < temp)) {
251
 
         temp = *ptr;
252
 
         for (i = 0; i < backtrack-1; i++) {
253
 
            ptr++;
254
 
            temp *= mAttackFactor;
255
 
            *ptr = temp;
256
 
         }
257
 
      }
258
 
      else
259
 
         *outEnv = level;
260
 
   }
261
 
 
262
 
   mLastLevel = *outEnv;
263
 
}
264
 
 
265
 
float AVDMProcessAudio_Compress::DoCompression(float value, double env)
266
 
{
267
 
   float mult;
268
 
   float out;
269
 
 
270
 
   if (env > mThreshold)
271
 
      mult = mGain * pow(mThreshold/env, 1.0/_param.mRatio);
272
 
   else
273
 
      mult = mGain;
274
 
 
275
 
   out = value * mult;
276
 
 
277
 
   if (out > 1.0)
278
 
      out = 1.0;
279
 
 
280
 
   if (out < -1.0)
281
 
      out = -1.0;
282
 
 
283
 
   return out;
284
 
}