summaryrefslogtreecommitdiff
path: root/src/input.cpp
blob: 59dd44e4ae9f60f525f0ff921dd11fed0b70180c (plain)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include <memory>
#include <string.h>
#include "debug.h"
#include "default_file.h"
#ifndef NO_FLAC
#include "input_flac.h"
#endif
#ifndef NO_DUMB
#include "input_mod.h"
#endif
#ifndef NO_MP3
#include "input_mp3.h"
#endif
#ifndef NO_OGG
#include "input_ogg.h"
#endif
#ifndef NO_SPEEX
#include "input_speex.h"
#endif
#include "input_wav.h"
#include "input_aiff.h"
#include "internal.h"
#include "utility.h"


namespace audiere {


  ADR_EXPORT(const char*) AdrGetSupportedFileFormats() {
    return
      "AIFF Files:aiff,aifc"  ";"
#ifndef NO_MP3
      "MP3 Files:mp3,mp2"  ";"
#endif
#ifndef NO_OGG
      "Ogg Vorbis Files:ogg"  ";"
#endif
#ifndef NO_FLAC
      "FLAC Files:flac"  ";"
#endif
#ifndef NO_DUMB
      "Mod Files:mod,s3m,xm,it"  ";"
#endif
#ifndef NO_SPEEX
      "Speex Files:spx"  ";"
#endif
      "WAV Files:wav";
  }


  template<typename T>
  static T* TryInputStream(const FilePtr& file) {

    // initialize should never close the file

    T* source = new T();
    if (source->initialize(file)) {
      return source;
    } else {
      delete source;
      return 0;
    }
  }


#define TRY_SOURCE(source_type) {                             \
  source_type* source = TryInputStream<source_type>(file);    \
  if (source) {                                               \
    return source;                                            \
  } else {                                                    \
    file->seek(0, File::BEGIN);                               \
  }                                                           \
}


#define TRY_OPEN(format) {                                    \
  SampleSource* source = OpenSource(file, filename, format);  \
  if (source) {                                               \
    return source;                                            \
  }                                                           \
}


  bool end_is(const char* begin, const char* ext) {
    const char* end = begin + strlen(begin);
    int ext_length = strlen(ext);
    if (ext_length > end - begin) {
      return false;
    } else {
      return (strcmp_case(end - ext_length, ext) == 0);
    }
  }


  FileFormat GuessFormat(const char* filename) {
    if (end_is(filename, ".aiff")) {
      return FF_AIFF;
    } else if (end_is(filename, ".wav")) {
      return FF_WAV;
    } else if (end_is(filename, ".ogg")) {
      return FF_OGG;
    } else if (end_is(filename, ".flac")) {
      return FF_FLAC;
    } else if (end_is(filename, ".mp3")) {
      return FF_MP3;
    } else if (end_is(filename, ".it") ||
               end_is(filename, ".xm") ||
               end_is(filename, ".s3m") ||
               end_is(filename, ".mod")) {
      return FF_MOD;
    } else if (end_is(filename, ".spx")) {
      return FF_SPEEX;
    } else {
      return FF_AUTODETECT;
    }
  }


  /**
   * The internal implementation of OpenSampleSource.
   *
   * @param file         the file to load from.  cannot be 0.
   * @param filename     the name of the file, or 0 if it is not available
   * @param file_format  the format of the file or FF_AUTODETECT
   */
  SampleSource* OpenSource(
    const FilePtr& file,
    const char* filename,
    FileFormat file_format)
  {
    ADR_GUARD("OpenSource");
    ADR_ASSERT(file != 0, "file must not be null");

    switch (file_format) {
      case FF_AUTODETECT:
        
        // if filename is available, use it as a hint
        if (filename) {
          FileFormat format = GuessFormat(filename);
          if (format != FF_AUTODETECT) {
            TRY_OPEN(format);
          }
        }

        // autodetect otherwise, in decreasing order of possibility of failure
        TRY_OPEN(FF_AIFF);
        TRY_OPEN(FF_WAV);
        TRY_OPEN(FF_MOD);
        TRY_OPEN(FF_OGG);
        TRY_OPEN(FF_FLAC);
        TRY_OPEN(FF_SPEEX);
        TRY_OPEN(FF_MP3);
        return 0;

#ifndef NO_DUMB
      case FF_MOD:
        TRY_SOURCE(MODInputStream);
        return 0;
#endif

      case FF_AIFF:
        TRY_SOURCE(AIFFInputStream);
        return 0;

      case FF_WAV:
        TRY_SOURCE(WAVInputStream);
        return 0;

#ifndef NO_OGG
      case FF_OGG:
        TRY_SOURCE(OGGInputStream);
        return 0;
#endif

#ifndef NO_MP3
      case FF_MP3:
        TRY_SOURCE(MP3InputStream);
        return 0;
#endif

#ifndef NO_FLAC
      case FF_FLAC:
        TRY_SOURCE(FLACInputStream);
        return 0;
#endif

#ifndef NO_SPEEX
      case FF_SPEEX:
        TRY_SOURCE(SpeexInputStream);
        return 0;
#endif

      default:
        return 0;
    }
  }


  ADR_EXPORT(SampleSource*) AdrOpenSampleSource(
    const char* filename,
    FileFormat file_format)
  {
    if (!filename) {
      return 0;
    }
    FilePtr file = OpenFile(filename, false);
    if (!file) {
      return 0;
    }
    return OpenSource(file, filename, file_format);
  }


  ADR_EXPORT(SampleSource*) AdrOpenSampleSourceFromFile(
    File* file,
    FileFormat file_format)
  {
    if (!file) {
      return 0;
    }
    return OpenSource(file, 0, file_format);
  }

}