On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / content / media / video / src / nsAudioStream.cpp
blob6b219868104da389bf5e12bf71863acb4e8f1a0c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla code.
18 * The Initial Developer of the Original Code is the Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2007
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Chris Double <chris.double@double.co.nz>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
38 #include <stdio.h>
39 #include <math.h>
40 #include "prlog.h"
41 #include "prmem.h"
42 #include "nsAutoPtr.h"
43 #include "nsAudioStream.h"
44 extern "C" {
45 #include "oggplay_audio/sydney_audio.h"
48 #ifdef PR_LOGGING
49 PRLogModuleInfo* gAudioStreamLog = nsnull;
50 #endif
52 nsresult nsAudioStream::InitLibrary()
54 #ifdef PR_LOGGING
55 gAudioStreamLog = PR_NewLogModule("nsAudioStream");
56 #endif
57 return NS_OK;
60 void nsAudioStream::ShutdownLibrary()
64 nsAudioStream::nsAudioStream() :
65 mVolume(1.0),
66 #if defined(SYDNEY_AUDIO_NO_POSITION)
67 mPauseTime(0.0),
68 #else
69 mPauseBytes(0),
70 #endif
71 mAudioHandle(0),
72 mRate(0),
73 mChannels(0),
74 mPaused(PR_FALSE)
78 nsresult nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate)
80 mRate = aRate;
81 mChannels = aNumChannels;
82 if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
83 NULL,
84 SA_MODE_WRONLY,
85 SA_PCM_FORMAT_S16_LE,
86 aRate,
87 aNumChannels) != SA_SUCCESS) {
88 mAudioHandle = nsnull;
89 PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_create_pcm error"));
90 return NS_OK;
93 if (sa_stream_open(reinterpret_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) {
94 sa_stream_destroy((sa_stream_t*)mAudioHandle);
95 mAudioHandle = nsnull;
96 PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_open error"));
97 return NS_OK;
100 #if defined(SYDNEY_AUDIO_NO_POSITION)
101 mPauseTime = double(PR_IntervalToMilliseconds(PR_IntervalNow()))/1000.0;
102 #endif
104 return NS_OK;
107 nsresult nsAudioStream::Shutdown()
109 if (!mAudioHandle)
110 return NS_OK;
112 sa_stream_destroy(reinterpret_cast<sa_stream_t*>(mAudioHandle));
113 mAudioHandle = nsnull;
115 return NS_OK;
118 nsresult nsAudioStream::Pause()
120 #if defined(USE_SYDNEY_AUDIO_OLD)
121 return NS_ERROR_NOT_IMPLEMENTED;
122 #else
123 if (mPaused)
124 return NS_OK;
126 mPaused = PR_TRUE;
128 if (!mAudioHandle)
129 return NS_OK;
131 #if defined(SYDNEY_AUDIO_NO_POSITION)
132 mPauseTime -= double(PR_IntervalToMilliseconds(PR_IntervalNow()))/1000.0;
133 #else
134 // The audio hardware resets the count of the number of bytes
135 // when paused so we need to save it.
136 int64_t bytes = 0;
137 sa_stream_get_position(reinterpret_cast<sa_stream_t*>(mAudioHandle), SA_POSITION_WRITE_SOFTWARE, &bytes);
138 mPauseBytes += bytes;
139 sa_stream_pause(reinterpret_cast<sa_stream_t*>(mAudioHandle));
140 #endif
142 return NS_OK;
143 #endif
146 nsresult nsAudioStream::Resume()
148 #if defined(USE_SYDNEY_AUDIO_OLD)
149 return NS_ERROR_NOT_IMPLEMENTED;
150 #else
151 if (!mPaused)
152 return NS_OK;
154 mPaused = PR_FALSE;
156 if (!mAudioHandle)
157 return NS_OK;
159 sa_stream_resume(reinterpret_cast<sa_stream_t*>(mAudioHandle));
161 #if defined(SYDNEY_AUDIO_NO_POSITION)
162 mPauseTime += double(PR_IntervalToMilliseconds(PR_IntervalNow()))/1000.0;
163 #endif
165 return NS_OK;
166 #endif
169 nsresult nsAudioStream::Write(float* aBuf, PRUint32 aCount)
171 if (!mAudioHandle)
172 return NS_OK;
174 // Convert array of floats, to an array of signed shorts
175 nsAutoArrayPtr<short> s_data(new short[aCount]);
177 if (s_data) {
178 for (PRUint32 i=0; i < aCount; ++i) {
179 float scaled_value = floorf(0.5 + 32768 * aBuf[i]);
180 if (aBuf[i] < 0.0) {
181 s_data[i] = (scaled_value < -32768.0) ?
182 -32768 :
183 short(scaled_value);
185 else {
186 s_data[i] = (scaled_value > 32767.0) ?
187 32767 :
188 short(scaled_value);
192 #if defined(SYDNEY_AUDIO_NO_VOLUME)
193 if (mVolume > 0.00001) {
194 #endif
195 if (sa_stream_write(reinterpret_cast<sa_stream_t*>(mAudioHandle), s_data.get(), aCount * sizeof(short)) != SA_SUCCESS) {
196 PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
197 Shutdown();
199 #if defined(SYDNEY_AUDIO_NO_VOLUME)
201 #endif
204 return NS_OK;
207 nsresult nsAudioStream::GetTime(double *aTime)
209 if (!aTime)
210 return NS_OK;
212 #if defined(SYDNEY_AUDIO_NO_POSITION)
213 *aTime = double(PR_IntervalToMilliseconds(PR_IntervalNow()))/1000.0 - mPauseTime;
214 #else
216 int64_t bytes = 0;
217 if (mAudioHandle) {
218 sa_stream_get_position(reinterpret_cast<sa_stream_t*>(mAudioHandle), SA_POSITION_WRITE_SOFTWARE, &bytes);
219 *aTime = double(((bytes + mPauseBytes) * 1000 / mRate / (sizeof(short) * mChannels))) / 1000.0;
221 else {
222 return NS_ERROR_NOT_IMPLEMENTED;
225 #endif
226 return NS_OK;
229 nsresult nsAudioStream::GetVolume(float *aVolume)
231 if (!aVolume)
232 return NS_OK;
234 #if defined(SYDNEY_AUDIO_NO_VOLUME)
235 *aVolume = mVolume;
236 #else
237 float volume = 0.0;
238 if (mAudioHandle) {
239 sa_stream_get_volume_abs(reinterpret_cast<sa_stream_t*>(mAudioHandle), &volume);
242 *aVolume = volume;
243 #endif
245 return NS_OK;
248 nsresult nsAudioStream::SetVolume(float aVolume)
250 #if defined(SYDNEY_AUDIO_NO_VOLUME)
251 mVolume = aVolume;
252 #else
253 if (!mAudioHandle)
254 return NS_OK;
256 sa_stream_set_volume_abs(reinterpret_cast<sa_stream_t*>(mAudioHandle), aVolume);
257 #endif
258 return NS_OK;