File: Timbre.cpp

package info (click to toggle)
between 6%2Bdfsg1-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, stretch
  • size: 3,532 kB
  • sloc: cpp: 28,110; php: 718; ansic: 638; objc: 245; sh: 236; makefile: 99; perl: 67
file content (164 lines) | stat: -rw-r--r-- 4,377 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "Timbre.h"

#include "minorGems/util/stringUtils.h"

#include <math.h>
#include <stdio.h>


double twelthRootOfTwo = pow( 2, 1.0/12 );

// for major scale
// W, W, H, W, W, W, H
int halfstepMap[ 7 ] = { 0, 2, 4, 5, 7, 9, 11 };

// minor scale
// W,H,W,W,H,W,W
//int halfstepMap[ 7 ] = { 0, 2, 3, 5, 7, 8, 10 };



// gets frequency of note in our scale
double getFrequency( double inBaseFrequency, int inScaleNoteNumber ) {
    int octavesUp = inScaleNoteNumber / 7;
    
    int numHalfsteps = halfstepMap[ inScaleNoteNumber % 7 ] + octavesUp * 12;
    
    return inBaseFrequency * pow( twelthRootOfTwo, numHalfsteps );
    }




/*
  Was used during testing

#include "minorGems/sound/formats/aiff.h"

int outputFileNumber = 0;


// outputs a wave table as an AIFF
void outputWaveTable( Sint16 *inTable, int inLength, int inSampleRate ) {
    // generate the header
    int headerSize;
    unsigned char *aiffHeader =
        getAIFFHeader( 1,
                       16,
                       inSampleRate,
                       inLength, 
                       &headerSize );

    char *fileName = autoSprintf( "waveTable%d.aiff", outputFileNumber );
    outputFileNumber++;
    

    FILE *aiffFile = fopen( fileName, "wb" );

    delete [] fileName;
    

    //printf( "Header size = %d\n", headerSize );
    
    fwrite( aiffHeader, 1, headerSize, aiffFile );

    delete [] aiffHeader;
    
    for( int i=0; i<inLength; i++ ) {
        Sint16 val = inTable[i];
        
        unsigned char msb = val >> 8 & 0xFF;
        unsigned char lsb = val && 0xFF;

        fwrite( &msb, 1, 1, aiffFile );
        fwrite( &lsb, 1, 1, aiffFile );
        }
    fclose( aiffFile );
    
    }
*/




Timbre::Timbre( int inSampleRate,
                double inLoudness,
                double inBaseFrequency,
                int inNumWaveTableEntries, 
                double( *inWaveFunction )( double ) )
        : mNumWaveTableEntries( inNumWaveTableEntries ),
          mWaveTable( new Sint16*[ inNumWaveTableEntries ] ),
          mWaveTableLengths( new int[ inNumWaveTableEntries ] ) {

    // build wave table for each possible pitch in image
    
    for( int i=0; i<mNumWaveTableEntries; i++ ) {
        double freq = getFrequency( inBaseFrequency, i );
        double period = 1.0 / freq;
        
        // wave table contains more than one period to more 
        // accurately represent a signal with frequency freq
        int periodsInTable = 5;
        int tableLength = (int)( periodsInTable * period * inSampleRate );
        
        mWaveTableLengths[i] = tableLength;
        mWaveTable[i] = new Sint16[ tableLength ];

        // store double samples in temp table so we can compute
        // max value for normalization
        double *tempTable = new double[ tableLength ];
        double maxValue = 0;
        
        int s;
        
        for( s=0; s<tableLength; s++ ) {
            //double t = (double)s / (double)inSampleRate;
            //double waveValue = inWaveFunction( 2 * M_PI * t * freq );
        
            // base t on table length to ensure a perfect set of periods
            // in our table.  Otherwise, we hear clicks when table is looped
            double t = (double)s / (double)(tableLength);
            double waveValue = inWaveFunction( 2 * M_PI * t * periodsInTable );
 
            tempTable[s] = waveValue;
            
            // track max value
            if( waveValue > maxValue ) {
                maxValue = waveValue;
                }
            else if( -waveValue > maxValue ) {
                maxValue = -waveValue;
                }
            }
        
        // now normalize and convert to int
        for( s=0; s<tableLength; s++ ) {
            double waveValue = tempTable[s] * inLoudness / maxValue;
            
            // convert to int
            mWaveTable[i][s] = (Sint16)( 32767 * waveValue );
            }
        
        delete [] tempTable;
        
                
        mWaveTableLengths[i] = tableLength;
        

        // to examine waveforms for testing
        // outputWaveTable( mWaveTable[i], tableLength, inSampleRate );
        
        }
    }


        
Timbre::~Timbre() {
    delete [] mWaveTableLengths;
    
    for( int i=0; i<mNumWaveTableEntries; i++ ) {
        delete [] mWaveTable[i];
        }
    delete [] mWaveTable;
    }