1 /*
2 * Copyright (c) 2012, The MilkyTracker Team.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * - Neither the name of the <ORGANIZATION> nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "AudioDriver_Haiku.h"
31 #include "MasterMixer.h"
32
33 #include <MediaDefs.h>
34 #include <MediaRoster.h>
35 #include <OS.h>
36 #include <SoundPlayer.h>
37
38 #include <stdio.h>
39 #include <string.h>
40
41
AudioDriver_Haiku()42 AudioDriver_Haiku::AudioDriver_Haiku()
43 :
44 AudioDriverBase(),
45 fSoundPlayer(NULL)
46 {
47 }
48
49
~AudioDriver_Haiku()50 AudioDriver_Haiku::~AudioDriver_Haiku()
51 {
52 delete fSoundPlayer;
53 }
54
55
56 // #pragma mark - AudioDriverBase API
57
58
59 mp_sint32
initDevice(mp_sint32 bufferSizeInWords,mp_uint32 mixFrequency,MasterMixer * mixer)60 AudioDriver_Haiku::initDevice(mp_sint32 bufferSizeInWords,
61 mp_uint32 mixFrequency, MasterMixer* mixer)
62 {
63 mp_sint32 result = AudioDriverBase::initDevice(bufferSizeInWords,
64 mixFrequency, mixer);
65 if (result < 0)
66 return result;
67
68 media_raw_audio_format format;
69 format.frame_rate = mixFrequency;
70 format.channel_count = kChannelCount;
71 format.format = media_raw_audio_format::B_AUDIO_SHORT;
72 format.byte_order = B_MEDIA_LITTLE_ENDIAN;
73 format.buffer_size = bufferSizeInWords * sizeof(mp_sword);
74
75 fSoundPlayer = new BSoundPlayer(&format, "Milky sound", _FillBuffer, NULL,
76 this);
77
78 status_t status = fSoundPlayer->InitCheck();
79 if (status != B_OK) {
80 fprintf(stderr, "AudioDriver_Haiku: failed to initialize "
81 "BSoundPlayer\n");
82 return MP_DEVICE_ERROR;
83 }
84
85 return MP_OK;
86 }
87
88
89 mp_sint32
closeDevice()90 AudioDriver_Haiku::closeDevice()
91 {
92 fSoundPlayer->SetHasData(false);
93 fSoundPlayer->Stop(true);
94 delete fSoundPlayer;
95 fSoundPlayer = NULL;
96 return MP_OK;
97 }
98
99
100 mp_sint32
start()101 AudioDriver_Haiku::start()
102 {
103 status_t status = fSoundPlayer->Start();
104 if (status != B_OK) {
105 fprintf(stderr, "AudioDriver_Haiku: failed to start BSoundPlayer\n");
106 return MP_DEVICE_ERROR;
107 }
108 fSoundPlayer->SetHasData(true);
109 return MP_OK;
110 }
111
112
113 mp_sint32
stop()114 AudioDriver_Haiku::stop()
115 {
116 fSoundPlayer->SetHasData(false);
117 fSoundPlayer->Stop(true);
118 return MP_OK;
119 }
120
121
122 mp_sint32
pause()123 AudioDriver_Haiku::pause()
124 {
125 fSoundPlayer->SetHasData(false);
126 }
127
128
129 mp_sint32
resume()130 AudioDriver_Haiku::resume()
131 {
132 fSoundPlayer->SetHasData(true);
133 }
134
135
136 mp_uint32
getNumPlayedSamples() const137 AudioDriver_Haiku::getNumPlayedSamples() const
138 {
139 bigtime_t time = fSoundPlayer->CurrentTime();
140 float samples = ((float)time / 1000000.0f) * mixFrequency;
141 return (mp_uint32)samples;
142 }
143
144
145 mp_sint32
getPreferredBufferSize() const146 AudioDriver_Haiku::getPreferredBufferSize() const
147 {
148 float frameRate = getPreferredSampleRate();
149 return BMediaRoster::Roster()->AudioBufferSizeFor(kChannelCount,
150 media_raw_audio_format::B_AUDIO_SHORT, frameRate, B_UNKNOWN_BUS);
151 }
152
153
154 // #pragma mark - MediaKit playback
155
156
157 void
_FillBuffer(void * theCookie,void * buffer,size_t size,const media_raw_audio_format & format)158 AudioDriver_Haiku::_FillBuffer(void* theCookie, void* buffer, size_t size,
159 const media_raw_audio_format& format)
160 {
161 AudioDriver_Haiku* audioDriver = (AudioDriver_Haiku*)theCookie;
162
163 MasterMixer* mixer = audioDriver->mixer;
164
165 if (audioDriver->isMixerActive())
166 mixer->mixerHandler((mp_sword*)buffer);
167 else
168 memset(buffer, 0, size);
169 }
170