cannam@162
|
1 // ---------------------------------------------------------------------------------------
|
cannam@162
|
2
|
cannam@162
|
3 #include <iostream>
|
cannam@162
|
4 #include <cmath>
|
cannam@162
|
5 #include <cassert>
|
cannam@162
|
6 #include <cstddef>
|
cannam@162
|
7 #include "portaudiocpp/PortAudioCpp.hxx"
|
cannam@162
|
8
|
cannam@162
|
9 // ---------------------------------------------------------------------------------------
|
cannam@162
|
10
|
cannam@162
|
11 // Some constants:
|
cannam@162
|
12 const int NUM_SECONDS = 5;
|
cannam@162
|
13 const double SAMPLE_RATE = 44100.0;
|
cannam@162
|
14 const int FRAMES_PER_BUFFER = 64;
|
cannam@162
|
15 const int TABLE_SIZE = 200;
|
cannam@162
|
16
|
cannam@162
|
17 // ---------------------------------------------------------------------------------------
|
cannam@162
|
18
|
cannam@162
|
19 // SineGenerator class:
|
cannam@162
|
20 class SineGenerator
|
cannam@162
|
21 {
|
cannam@162
|
22 public:
|
cannam@162
|
23 SineGenerator(int tableSize) : tableSize_(tableSize), leftPhase_(0), rightPhase_(0)
|
cannam@162
|
24 {
|
cannam@162
|
25 const double PI = 3.14159265;
|
cannam@162
|
26 table_ = new float[tableSize];
|
cannam@162
|
27 for (int i = 0; i < tableSize; ++i)
|
cannam@162
|
28 {
|
cannam@162
|
29 table_[i] = 0.125f * (float)sin(((double)i/(double)tableSize)*PI*2.);
|
cannam@162
|
30 }
|
cannam@162
|
31 }
|
cannam@162
|
32
|
cannam@162
|
33 ~SineGenerator()
|
cannam@162
|
34 {
|
cannam@162
|
35 delete[] table_;
|
cannam@162
|
36 }
|
cannam@162
|
37
|
cannam@162
|
38 int generate(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
|
cannam@162
|
39 const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags)
|
cannam@162
|
40 {
|
cannam@162
|
41 assert(outputBuffer != NULL);
|
cannam@162
|
42
|
cannam@162
|
43 float **out = static_cast<float **>(outputBuffer);
|
cannam@162
|
44
|
cannam@162
|
45 for (unsigned int i = 0; i < framesPerBuffer; ++i)
|
cannam@162
|
46 {
|
cannam@162
|
47 out[0][i] = table_[leftPhase_];
|
cannam@162
|
48 out[1][i] = table_[rightPhase_];
|
cannam@162
|
49
|
cannam@162
|
50 leftPhase_ += 1;
|
cannam@162
|
51 if (leftPhase_ >= tableSize_)
|
cannam@162
|
52 leftPhase_ -= tableSize_;
|
cannam@162
|
53
|
cannam@162
|
54 rightPhase_ += 3;
|
cannam@162
|
55 if (rightPhase_ >= tableSize_)
|
cannam@162
|
56 rightPhase_ -= tableSize_;
|
cannam@162
|
57 }
|
cannam@162
|
58
|
cannam@162
|
59 return paContinue;
|
cannam@162
|
60 }
|
cannam@162
|
61
|
cannam@162
|
62 private:
|
cannam@162
|
63 float *table_;
|
cannam@162
|
64 int tableSize_;
|
cannam@162
|
65 int leftPhase_;
|
cannam@162
|
66 int rightPhase_;
|
cannam@162
|
67 };
|
cannam@162
|
68
|
cannam@162
|
69 // ---------------------------------------------------------------------------------------
|
cannam@162
|
70
|
cannam@162
|
71 // main:
|
cannam@162
|
72 int main(int, char *[]);
|
cannam@162
|
73 int main(int, char *[])
|
cannam@162
|
74 {
|
cannam@162
|
75 try
|
cannam@162
|
76 {
|
cannam@162
|
77 // Create a SineGenerator object:
|
cannam@162
|
78 SineGenerator sineGenerator(TABLE_SIZE);
|
cannam@162
|
79
|
cannam@162
|
80 std::cout << "Setting up PortAudio..." << std::endl;
|
cannam@162
|
81
|
cannam@162
|
82 // Set up the System:
|
cannam@162
|
83 portaudio::AutoSystem autoSys;
|
cannam@162
|
84 portaudio::System &sys = portaudio::System::instance();
|
cannam@162
|
85
|
cannam@162
|
86 // Set up the parameters required to open a (Callback)Stream:
|
cannam@162
|
87 portaudio::DirectionSpecificStreamParameters outParams(sys.defaultOutputDevice(), 2, portaudio::FLOAT32, false, sys.defaultOutputDevice().defaultLowOutputLatency(), NULL);
|
cannam@162
|
88 portaudio::StreamParameters params(portaudio::DirectionSpecificStreamParameters::null(), outParams, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff);
|
cannam@162
|
89
|
cannam@162
|
90 std::cout << "Opening stereo output stream..." << std::endl;
|
cannam@162
|
91
|
cannam@162
|
92 // Create (and open) a new Stream, using the SineGenerator::generate function as a callback:
|
cannam@162
|
93 portaudio::MemFunCallbackStream<SineGenerator> stream(params, sineGenerator, &SineGenerator::generate);
|
cannam@162
|
94
|
cannam@162
|
95 std::cout << "Starting playback for " << NUM_SECONDS << " seconds." << std::endl;
|
cannam@162
|
96
|
cannam@162
|
97 // Start the Stream (audio playback starts):
|
cannam@162
|
98 stream.start();
|
cannam@162
|
99
|
cannam@162
|
100 // Wait for 5 seconds:
|
cannam@162
|
101 sys.sleep(NUM_SECONDS * 1000);
|
cannam@162
|
102
|
cannam@162
|
103 std::cout << "Closing stream..." <<std::endl;
|
cannam@162
|
104
|
cannam@162
|
105 // Stop the Stream (not strictly needed as termintating the System will also stop all open Streams):
|
cannam@162
|
106 stream.stop();
|
cannam@162
|
107
|
cannam@162
|
108 // Close the Stream (not strictly needed as terminating the System will also close all open Streams):
|
cannam@162
|
109 stream.close();
|
cannam@162
|
110
|
cannam@162
|
111 // Terminate the System (not strictly needed as the AutoSystem will also take care of this when it
|
cannam@162
|
112 // goes out of scope):
|
cannam@162
|
113 sys.terminate();
|
cannam@162
|
114
|
cannam@162
|
115 std::cout << "Test finished." << std::endl;
|
cannam@162
|
116 }
|
cannam@162
|
117 catch (const portaudio::PaException &e)
|
cannam@162
|
118 {
|
cannam@162
|
119 std::cout << "A PortAudio error occured: " << e.paErrorText() << std::endl;
|
cannam@162
|
120 }
|
cannam@162
|
121 catch (const portaudio::PaCppException &e)
|
cannam@162
|
122 {
|
cannam@162
|
123 std::cout << "A PortAudioCpp error occured: " << e.what() << std::endl;
|
cannam@162
|
124 }
|
cannam@162
|
125 catch (const std::exception &e)
|
cannam@162
|
126 {
|
cannam@162
|
127 std::cout << "A generic exception occured: " << e.what() << std::endl;
|
cannam@162
|
128 }
|
cannam@162
|
129 catch (...)
|
cannam@162
|
130 {
|
cannam@162
|
131 std::cout << "An unknown exception occured." << std::endl;
|
cannam@162
|
132 }
|
cannam@162
|
133
|
cannam@162
|
134 return 0;
|
cannam@162
|
135 }
|
cannam@162
|
136
|
cannam@162
|
137
|