~mixxxdevelopers/mixxx/features_library_scanner

« back to all changes in this revision

Viewing changes to mixxx/mixxx/soundsource.cpp

  • Committer: tuehaste
  • Date: 2002-02-26 11:12:07 UTC
  • Revision ID: vcs-imports@canonical.com-20020226111207-5rly26cj9gdd19ba
Initial revision

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                          soundsource.cpp  -  description
 
3
                             -------------------
 
4
    begin                : Wed Feb 20 2002
 
5
    copyright            : (C) 2002 by Tue and Ken Haste Andersen
 
6
    email                : 
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
11
 *   This program is free software; you can redistribute it and/or modify  *
 
12
 *   it under the terms of the GNU General Public License as published by  *
 
13
 *   the Free Software Foundation; either version 2 of the License, or     *
 
14
 *   (at your option) any later version.                                   *
 
15
 *                                                                         *
 
16
 ***************************************************************************/
 
17
 
 
18
#include "soundsource.h"
 
19
 
 
20
   /*
 
21
  SoundSource is a Uber-class for the reading and decoding of audio-files.
 
22
  Each class must have the following member functions:
 
23
    initializer with a filename
 
24
    seek()
 
25
    read()
 
26
    length()
 
27
*/
 
28
SoundSource::SoundSource() {}
 
29
SoundSource::~SoundSource() {}
 
30
/*
 
31
  Class for reading files using libaudiofile
 
32
*/
 
33
AFlibfile::AFlibfile(const char* filename) {
 
34
  fh = afOpenFile(filename,"r",0);
 
35
  if (fh == AF_NULL_FILEHANDLE) {
 
36
    cout << "Error opening file.\n";
 
37
    exit(1);
 
38
  }
 
39
  channels = 2;
 
40
  filelength = 2*afGetFrameCount(fh,AF_DEFAULT_TRACK);
 
41
}
 
42
 
 
43
AFlibfile::~AFlibfile() {
 
44
  afCloseFile(fh);
 
45
};
 
46
 
 
47
long AFlibfile::seek(long filepos) {
 
48
  afSeekFrame(fh, AF_DEFAULT_TRACK, (AFframecount) (filepos/channels));
 
49
  return filepos;
 
50
}
 
51
/*
 
52
  read <size> samples into <destination>, and return the number of
 
53
  samples actually read.
 
54
*/
 
55
unsigned AFlibfile::read(unsigned long size, const SAMPLE* destination) {
 
56
  return afReadFrames(fh,AF_DEFAULT_TRACK, (SAMPLE *)destination
 
57
                      ,size/channels)*channels;
 
58
}
 
59
/*
 
60
  Return the length of the file in samples.
 
61
*/
 
62
long unsigned AFlibfile::length() {
 
63
  return filelength;
 
64
}
 
65
 
 
66
/*
 
67
  Reading and decoding of mp3-files:
 
68
*/
 
69
mp3file::mp3file(const char* filename) {
 
70
  // Open the file:
 
71
  file = fopen(filename,"r");
 
72
  if (!file) {
 
73
        cout << "Open of " << filename << " failed\n" << flush;
 
74
        exit(-1);
 
75
  }
 
76
  // Read in the whole file into inputbuf:
 
77
  struct stat filestat;
 
78
  stat(filename, &filestat);
 
79
  mp3filelength = filestat.st_size;
 
80
  inputbuf_len = mp3filelength;
 
81
  inputbuf = new unsigned char[inputbuf_len];
 
82
        if (fread(inputbuf,1,mp3filelength,file) != mp3filelength)
 
83
          cout << "Error reading mp3-file.\n" << flush;
 
84
        // Transfer it to the mad stream-buffer:
 
85
  mad_stream_init(&Stream);
 
86
  mad_stream_buffer(&Stream, inputbuf, mp3filelength);
 
87
  /*
 
88
    Read and decode the header:
 
89
  */
 
90
  mad_header Header;
 
91
  mad_header_init(&Header);
 
92
  // Make a table of the frames:
 
93
  long total_bytes = 0;
 
94
  while (mad_header_decode(&Header, &Stream) == 0) {
 
95
    ftable.push_back((long)(Stream.this_frame - Stream.buffer));
 
96
    sampletable.push_back(total_bytes/2);
 
97
    bitrate = Header.bitrate/1000;
 
98
    total_bytes +=
 
99
 (Stream.next_frame-Stream.this_frame)*SRATE*8*4/(bitrate*1000);
 
100
    cout <<
 
101
 ftable[ftable.size()-1]<<":"<<sampletable[ftable.size()-1]<<":"<<bitrate << "..
 
102
 ";
 
103
  }
 
104
  total_bytes +=
 
105
    (mp3filelength -
 
106
 (Stream.this_frame-Stream.buffer))*SRATE*8*4/(bitrate*1000);
 
107
  // Calc the length of the file:
 
108
  filelength = total_bytes/2; // filelength is measured in samples.
 
109
  mad_header_finish(&Header);
 
110
  // Re-init buffer:
 
111
  mad_stream_finish(&Stream);
 
112
  mad_stream_init(&Stream);
 
113
  mad_stream_buffer(&Stream, inputbuf, mp3filelength);
 
114
  cout << filelength << ":" << bitrate <<"\n";
 
115
}
 
116
 
 
117
mp3file::~mp3file() {
 
118
  fclose(file);
 
119
  delete inputbuf;
 
120
  mad_stream_finish(&Stream);
 
121
  mad_frame_finish(&Frame);
 
122
  mad_synth_finish(&Synth);
 
123
}
 
124
/*
 
125
   Seek towards filepos (in samples). Return the position which was actually
 
126
   found.
 
127
*/
 
128
long mp3file::seek(long filepos) {
 
129
  int i;
 
130
  for (i=0; (i<ftable.size()) && (sampletable[i]<filepos); i++);
 
131
  // Re-init buffer:
 
132
  mad_stream_finish(&Stream);
 
133
  mad_stream_init(&Stream);
 
134
  mad_stream_buffer(&Stream, inputbuf+ftable[i], mp3filelength-ftable[i]);
 
135
  cout << ftable[i] << "\n";
 
136
  return sampletable[i];
 
137
}
 
138
 
 
139
/*
 
140
  Read <samples_wanted> samples into the buffer <destination>.
 
141
*/
 
142
unsigned mp3file::read(unsigned long samples_wanted, const SAMPLE* _destination)
 
143
 {
 
144
  SAMPLE *destination = (SAMPLE*)_destination;
 
145
  unsigned Total_samples_decoded = 0;
 
146
 
 
147
  while (Total_samples_decoded < samples_wanted) {
 
148
    cout << Total_samples_decoded << ",";
 
149
    if(mad_frame_decode(&Frame,&Stream))
 
150
      if(MAD_RECOVERABLE(Stream.error))
 
151
        {
 
152
          fprintf(stderr,"Recoverable frame level error (%s)\n",
 
153
            mad_stream_errorstr(&Stream));
 
154
          fflush(stderr);
 
155
          continue;
 
156
        }
 
157
      else
 
158
        if(Stream.error==MAD_ERROR_BUFLEN)
 
159
          continue;
 
160
        else
 
161
          {
 
162
            fprintf(stderr,"Unrecoverable frame level error (%s).\n",
 
163
                    mad_stream_errorstr(&Stream));
 
164
            break;
 
165
          }
 
166
    /* Once decoded the frame is synthesized to PCM samples. No errors
 
167
     * are reported by mad_synth_frame();
 
168
     */
 
169
    mad_synth_frame(&Synth,&Frame);
 
170
    /* Synthesized samples must be converted from mad's fixed
 
171
     * point number to the consumer format. Here we use unsigned
 
172
     * 16 bit big endian integers on two channels. Integer samples
 
173
     * are temporarily stored in a buffer that is flushed when
 
174
     * full.
 
175
     */
 
176
    for(int i=0;i<Synth.pcm.length;i++)
 
177
      {
 
178
        unsigned short  Sample;
 
179
        /* Left channel */
 
180
        Sample=(SAMPLE)(Synth.pcm.samples[0][i]>>(MAD_F_FRACBITS-15));
 
181
        *(destination++) = Sample;
 
182
        /* Right channel. If the decoded stream is monophonic then
 
183
         * the right output channel is the same as the left one.
 
184
         */
 
185
        if(MAD_NCHANNELS(&Frame.header)==2)
 
186
          Sample=(SAMPLE)(Synth.pcm.samples[0][i]>>(MAD_F_FRACBITS-15));
 
187
        *(destination++) = Sample;
 
188
      }
 
189
    Total_samples_decoded += 2*Synth.pcm.length;
 
190
  }
 
191
 
 
192
  cout << "decoded " << Total_samples_decoded << "\n" << flush;
 
193
 
 
194
  return Total_samples_decoded;
 
195
}
 
196
 
 
197
long unsigned mp3file::length() {
 
198
    return filelength;
 
199
}