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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "WebAudioUtils.h"
8 #include "AudioNodeTrack.h"
9 #include "blink/HRTFDatabaseLoader.h"
10
11 #include "nsComponentManagerUtils.h"
12 #include "nsContentUtils.h"
13 #include "nsIConsoleService.h"
14 #include "nsIScriptError.h"
15 #include "nsJSUtils.h"
16 #include "nsServiceManagerUtils.h"
17 #include "AudioEventTimeline.h"
18
19 #include "mozilla/SchedulerGroup.h"
20
21 namespace mozilla {
22
23 LazyLogModule gWebAudioAPILog("WebAudioAPI");
24
25 namespace dom {
26
ConvertAudioTimelineEventToTicks(AudioTimelineEvent & aEvent,AudioNodeTrack * aDest)27 void WebAudioUtils::ConvertAudioTimelineEventToTicks(AudioTimelineEvent& aEvent,
28 AudioNodeTrack* aDest) {
29 aEvent.SetTimeInTicks(
30 aDest->SecondsToNearestTrackTime(aEvent.Time<double>()));
31 aEvent.mTimeConstant *= aDest->mSampleRate;
32 aEvent.mDuration *= aDest->mSampleRate;
33 }
34
Shutdown()35 void WebAudioUtils::Shutdown() { WebCore::HRTFDatabaseLoader::shutdown(); }
36
SpeexResamplerProcess(SpeexResamplerState * aResampler,uint32_t aChannel,const float * aIn,uint32_t * aInLen,float * aOut,uint32_t * aOutLen)37 int WebAudioUtils::SpeexResamplerProcess(SpeexResamplerState* aResampler,
38 uint32_t aChannel, const float* aIn,
39 uint32_t* aInLen, float* aOut,
40 uint32_t* aOutLen) {
41 #ifdef MOZ_SAMPLE_TYPE_S16
42 AutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 4> tmp1;
43 AutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 4> tmp2;
44 tmp1.SetLength(*aInLen);
45 tmp2.SetLength(*aOutLen);
46 ConvertAudioSamples(aIn, tmp1.Elements(), *aInLen);
47 int result = speex_resampler_process_int(
48 aResampler, aChannel, tmp1.Elements(), aInLen, tmp2.Elements(), aOutLen);
49 ConvertAudioSamples(tmp2.Elements(), aOut, *aOutLen);
50 return result;
51 #else
52 return speex_resampler_process_float(aResampler, aChannel, aIn, aInLen, aOut,
53 aOutLen);
54 #endif
55 }
56
SpeexResamplerProcess(SpeexResamplerState * aResampler,uint32_t aChannel,const int16_t * aIn,uint32_t * aInLen,float * aOut,uint32_t * aOutLen)57 int WebAudioUtils::SpeexResamplerProcess(SpeexResamplerState* aResampler,
58 uint32_t aChannel, const int16_t* aIn,
59 uint32_t* aInLen, float* aOut,
60 uint32_t* aOutLen) {
61 AutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 4> tmp;
62 #ifdef MOZ_SAMPLE_TYPE_S16
63 tmp.SetLength(*aOutLen);
64 int result = speex_resampler_process_int(aResampler, aChannel, aIn, aInLen,
65 tmp.Elements(), aOutLen);
66 ConvertAudioSamples(tmp.Elements(), aOut, *aOutLen);
67 return result;
68 #else
69 tmp.SetLength(*aInLen);
70 ConvertAudioSamples(aIn, tmp.Elements(), *aInLen);
71 int result = speex_resampler_process_float(
72 aResampler, aChannel, tmp.Elements(), aInLen, aOut, aOutLen);
73 return result;
74 #endif
75 }
76
SpeexResamplerProcess(SpeexResamplerState * aResampler,uint32_t aChannel,const int16_t * aIn,uint32_t * aInLen,int16_t * aOut,uint32_t * aOutLen)77 int WebAudioUtils::SpeexResamplerProcess(SpeexResamplerState* aResampler,
78 uint32_t aChannel, const int16_t* aIn,
79 uint32_t* aInLen, int16_t* aOut,
80 uint32_t* aOutLen) {
81 #ifdef MOZ_SAMPLE_TYPE_S16
82 return speex_resampler_process_int(aResampler, aChannel, aIn, aInLen, aOut,
83 aOutLen);
84 #else
85 AutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 4> tmp1;
86 AutoTArray<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 4> tmp2;
87 tmp1.SetLength(*aInLen);
88 tmp2.SetLength(*aOutLen);
89 ConvertAudioSamples(aIn, tmp1.Elements(), *aInLen);
90 int result = speex_resampler_process_float(
91 aResampler, aChannel, tmp1.Elements(), aInLen, tmp2.Elements(), aOutLen);
92 ConvertAudioSamples(tmp2.Elements(), aOut, *aOutLen);
93 return result;
94 #endif
95 }
96
LogToDeveloperConsole(uint64_t aWindowID,const char * aKey)97 void WebAudioUtils::LogToDeveloperConsole(uint64_t aWindowID,
98 const char* aKey) {
99 // This implementation is derived from dom/media/VideoUtils.cpp, but we
100 // use a windowID so that the message is delivered to the developer console.
101 // It is similar to ContentUtils::ReportToConsole, but also works off main
102 // thread.
103 if (!NS_IsMainThread()) {
104 nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
105 "dom::WebAudioUtils::LogToDeveloperConsole",
106 [aWindowID, aKey] { LogToDeveloperConsole(aWindowID, aKey); });
107 SchedulerGroup::Dispatch(TaskCategory::Other, task.forget());
108 return;
109 }
110
111 nsCOMPtr<nsIConsoleService> console(
112 do_GetService("@mozilla.org/consoleservice;1"));
113 if (!console) {
114 NS_WARNING("Failed to log message to console.");
115 return;
116 }
117
118 nsAutoString spec;
119 uint32_t aLineNumber = 0, aColumnNumber = 0;
120 JSContext* cx = nsContentUtils::GetCurrentJSContext();
121 if (cx) {
122 nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
123 }
124
125 nsresult rv;
126 nsCOMPtr<nsIScriptError> errorObject =
127 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
128 if (!errorObject) {
129 NS_WARNING("Failed to log message to console.");
130 return;
131 }
132
133 nsAutoString result;
134 rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, aKey,
135 result);
136
137 if (NS_FAILED(rv)) {
138 NS_WARNING("Failed to log message to console.");
139 return;
140 }
141
142 errorObject->InitWithWindowID(result, spec, u""_ns, aLineNumber,
143 aColumnNumber, nsIScriptError::warningFlag,
144 "Web Audio", aWindowID);
145 console->LogMessage(errorObject);
146 }
147
148 } // namespace dom
149 } // namespace mozilla
150