~ubuntu-branches/ubuntu/vivid/emscripten/vivid-proposed

« back to all changes in this revision

Viewing changes to tests/sdl_audio_beep.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2014-01-19 14:12:40 UTC
  • mfrom: (4.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140119141240-nfiw0p8033oitpfz
Tags: 1.9.0~20140119~7dc8c2f-1
* New snapshot release (Closes: #733714)
* Provide sources for javascript and flash. Done in orig-tar.sh
  Available in third_party/websockify/include/web-socket-js/src/
  (Closes: #735903)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <SDL/SDL.h>
 
2
#include <SDL/SDL_audio.h>
 
3
#include <queue>
 
4
#include <cmath>
 
5
#include <stdio.h>
 
6
#include <assert.h>
 
7
 
 
8
#ifndef M_PI
 
9
#define M_PI 3.14159265358979323846f
 
10
#endif
 
11
 
 
12
#ifdef EMSCRIPTEN
 
13
#include "emscripten/emscripten.h"
 
14
#endif
 
15
 
 
16
#ifdef main
 
17
#undef main
 
18
#endif
 
19
 
 
20
const int tone_duration = 1000;
 
21
 
 
22
struct BeepObject {
 
23
  double toneFrequency;
 
24
  int samplesLeft;
 
25
};
 
26
 
 
27
class Beeper {
 
28
private:
 
29
  double phase;
 
30
  int frequency;
 
31
  int numChannels;
 
32
  int mutedChannel;
 
33
public:
 
34
  Beeper(int frequency, int numChannels, int sdlAudioFormat);
 
35
  ~Beeper();
 
36
  void beep(double toneFrequency, int durationMSecs);
 
37
  template<typename T>
 
38
  void generateSamples(T *stream, int length);
 
39
  void wait();
 
40
 
 
41
  std::queue<BeepObject> beeps;
 
42
  int sdlAudioFormat;
 
43
};
 
44
 
 
45
void audio_callback(void*, Uint8*, int);
 
46
 
 
47
Beeper::Beeper(int frequency_, int numChannels_, int sdlAudioFormat_) {
 
48
  phase = 0.0;
 
49
  mutedChannel = 1;
 
50
 
 
51
  SDL_AudioSpec desiredSpec;
 
52
 
 
53
  desiredSpec.freq = frequency_;
 
54
  desiredSpec.format = sdlAudioFormat_;
 
55
  desiredSpec.channels = numChannels_;
 
56
  desiredSpec.samples = 1024; // This is samples per channel.
 
57
  desiredSpec.callback = audio_callback;
 
58
  desiredSpec.userdata = this;
 
59
 
 
60
  SDL_AudioSpec obtainedSpec;
 
61
 
 
62
  // you might want to look for errors here
 
63
  SDL_OpenAudio(&desiredSpec, &obtainedSpec);
 
64
 
 
65
  // In this test, we require *exactly* the identical SDL result that we provide, since we test
 
66
  // all various configurations individually.
 
67
  if (obtainedSpec.freq != desiredSpec.freq || obtainedSpec.format != desiredSpec.format
 
68
    || obtainedSpec.channels != desiredSpec.channels || obtainedSpec.samples != desiredSpec.samples) {
 
69
    SDL_CloseAudio();
 
70
    throw std::runtime_error("Failed to initialize desired SDL_OpenAudio!");
 
71
  }
 
72
 
 
73
  frequency = obtainedSpec.freq;
 
74
  numChannels = obtainedSpec.channels;
 
75
  sdlAudioFormat = obtainedSpec.format;
 
76
 
 
77
  // Immediately start producing audio.
 
78
  SDL_PauseAudio(0);
 
79
}
 
80
 
 
81
Beeper::~Beeper() {
 
82
  SDL_CloseAudio();
 
83
}
 
84
 
 
85
template<typename T>
 
86
void Beeper::generateSamples(T *stream, int length) {
 
87
  const int AMPLITUDE = (sizeof(T) == 2) ? 28000 : 120;
 
88
  const int offset = (sdlAudioFormat == AUDIO_U8) ? 120 : 0;
 
89
 
 
90
  int i = 0;
 
91
  length /= numChannels;
 
92
  while (i < length) {
 
93
    if (beeps.empty()) {
 
94
      memset(stream + numChannels*i, 0, sizeof(T)*numChannels*(length-i));
 
95
      return;
 
96
    }
 
97
    BeepObject& bo = beeps.front();
 
98
 
 
99
    // In Stereo tests, mute one of the channels to be able to distinguish that Stereo output works.
 
100
    if (bo.samplesLeft > tone_duration * frequency / 2 / 1000) {
 
101
      mutedChannel = 1;
 
102
    } else {
 
103
      mutedChannel = 0;
 
104
    }
 
105
 
 
106
    int samplesToDo = std::min(i + bo.samplesLeft, length);
 
107
    bo.samplesLeft -= samplesToDo - i;
 
108
 
 
109
    while (i < samplesToDo) {
 
110
      for(int j = 0; j < numChannels; ++j) {
 
111
        stream[numChannels*i+j] = (T)(offset + (int)(AMPLITUDE * std::sin(phase * 2 * M_PI / frequency)));
 
112
        if (numChannels > 1 && j == mutedChannel) {
 
113
          stream[numChannels*i+j] = 0;
 
114
        }
 
115
      }
 
116
      phase += bo.toneFrequency;
 
117
      i++;
 
118
    }
 
119
 
 
120
    if (bo.samplesLeft == 0) {
 
121
      beeps.pop();
 
122
    }
 
123
  }
 
124
}
 
125
 
 
126
void Beeper::beep(double toneFrequency, int durationMSecs) {
 
127
  BeepObject bo;
 
128
  bo.toneFrequency = toneFrequency;
 
129
  bo.samplesLeft = durationMSecs * frequency / 1000;
 
130
 
 
131
  SDL_LockAudio();
 
132
  beeps.push(bo);
 
133
  SDL_UnlockAudio();
 
134
}
 
135
 
 
136
Beeper *beep = 0;
 
137
 
 
138
// Test all kinds of various possible formats. Not all are supported, but running this
 
139
// test will report you which work.
 
140
const int freqs[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000 };
 
141
const int channels[] = { 1, 2 };
 
142
const int sdlAudioFormats[] = { AUDIO_U8, AUDIO_S16LSB /*, AUDIO_S8, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16MSB */ };
 
143
 
 
144
const char *SdlAudioFormatToString(int sdlAudioType) {
 
145
  switch(sdlAudioType) {
 
146
  case AUDIO_U8: return "AUDIO_U8";
 
147
  case AUDIO_S8: return "AUDIO_S8";
 
148
  case AUDIO_U16LSB: return "AUDIO_U16LSB";
 
149
  case AUDIO_U16MSB: return "AUDIO_U16MSB";
 
150
  case AUDIO_S16LSB: return "AUDIO_S16LSB";
 
151
  case AUDIO_S16MSB: return "AUDIO_S16MSB";
 
152
  default: return "(unknown)";
 
153
  }
 
154
}
 
155
 
 
156
#define NUM_ELEMS(x) (sizeof(x)/sizeof((x)[0]))
 
157
 
 
158
// Indices to the currently running test.
 
159
int f = -1;
 
160
int c = 0;
 
161
int s = 0;
 
162
 
 
163
void nextTest(void *unused = 0) {
 
164
  ++f;
 
165
  if (f >= NUM_ELEMS(freqs)) {
 
166
    f = 0;
 
167
    ++c;
 
168
    if (c >= NUM_ELEMS(channels)) {
 
169
      c = 0;
 
170
      ++s;
 
171
      if (s >= NUM_ELEMS(sdlAudioFormats)) {
 
172
        printf("All tests done. Quit.\n");
 
173
#ifdef EMSCRIPTEN
 
174
        emscripten_cancel_main_loop();
 
175
#ifdef REPORT_RESULT
 
176
        int result = 1;
 
177
        REPORT_RESULT();
 
178
#endif
 
179
#endif
 
180
        return;
 
181
      }
 
182
    }
 
183
  }
 
184
 
 
185
  double Hz = 440;
 
186
  try {
 
187
    beep = new Beeper(freqs[f], channels[c], sdlAudioFormats[s]);
 
188
  } catch(...) {
 
189
    printf("FAILED to play beep for %d msecs at %d Hz tone with audio format %s, %d channels, and %d samples/sec.\n",
 
190
        tone_duration, (int)Hz, SdlAudioFormatToString(sdlAudioFormats[s]), channels[c], freqs[f]);
 
191
    nextTest();
 
192
    return;
 
193
  }
 
194
 
 
195
  printf("Playing back a beep for %d msecs at %d Hz tone with audio format %s, %d channels, and %d samples/sec.\n",
 
196
      tone_duration, (int)Hz, SdlAudioFormatToString(sdlAudioFormats[s]), channels[c], freqs[f]);
 
197
  beep->beep(Hz, tone_duration);
 
198
}
 
199
 
 
200
void update() {
 
201
  SDL_LockAudio();
 
202
  int size = beep->beeps.size();
 
203
  SDL_UnlockAudio();
 
204
  if (size == 0 && beep) {
 
205
    delete beep;
 
206
    beep = 0;
 
207
#ifdef EMSCRIPTEN
 
208
    emscripten_async_call(nextTest, 0, 1500);
 
209
#else
 
210
    SDL_Delay(1500);
 
211
    nextTest();
 
212
#endif
 
213
  }
 
214
}
 
215
 
 
216
void audio_callback(void *_beeper, Uint8 *_stream, int _length) {
 
217
  Beeper* beeper = (Beeper*) _beeper;
 
218
 
 
219
  if (beeper->sdlAudioFormat == AUDIO_U8) {
 
220
    Uint8 *stream = (Uint8*) _stream;
 
221
    beeper->generateSamples(stream, _length);
 
222
  } else if (beeper->sdlAudioFormat == AUDIO_S16LSB) {
 
223
    Sint16 *stream = (Sint16*) _stream;
 
224
    int length = _length / 2;
 
225
    beeper->generateSamples(stream, length);
 
226
  } else {
 
227
    assert(false && "Audio sample generation not implemented for current format!\n");
 
228
  }
 
229
}
 
230
 
 
231
int main(int argc, char** argv) {
 
232
  SDL_Init(SDL_INIT_AUDIO);
 
233
 
 
234
  nextTest();
 
235
   
 
236
#ifdef EMSCRIPTEN
 
237
  emscripten_set_main_loop(update, 60, 0);
 
238
#else
 
239
  while(beep) {
 
240
    SDL_Delay(20);
 
241
    update();
 
242
  }
 
243
#endif
 
244
 
 
245
  return 0;
 
246
}