1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* EnvironmentalReverb implementation */
18
19#include "sles_allinclusive.h"
20#ifdef ANDROID
21#include <system/audio_effects/effect_environmentalreverb.h>
22#endif
23
24// Note: all Set operations use exclusive not poke,
25// because SetEnvironmentalReverbProperties is exclusive.
26// It is safe for the Get operations to use peek,
27// on the assumption that the block copy will atomically
28// replace each word of the block.
29
30
31#if defined(ANDROID)
32/**
33 * returns true if this interface is not associated with an initialized EnvironmentalReverb effect
34 */
35static inline bool NO_ENVREVERB(IEnvironmentalReverb* ier) {
36    return (ier->mEnvironmentalReverbEffect == 0);
37}
38#endif
39
40
41static SLresult IEnvironmentalReverb_SetRoomLevel(SLEnvironmentalReverbItf self, SLmillibel room)
42{
43    SL_ENTER_INTERFACE
44
45    //if (!(SL_MILLIBEL_MIN <= room && room <= 0)) {
46    // comparison (SL_MILLIBEL_MIN <= room) is always true due to range of SLmillibel
47    if (!(room <= 0)) {
48        result = SL_RESULT_PARAMETER_INVALID;
49    } else {
50        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
51        interface_lock_exclusive(thiz);
52        thiz->mProperties.roomLevel = room;
53#if !defined(ANDROID)
54        result = SL_RESULT_SUCCESS;
55#else
56        if (NO_ENVREVERB(thiz)) {
57            result = SL_RESULT_CONTROL_LOST;
58        } else {
59            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
60                    REVERB_PARAM_ROOM_LEVEL, &room);
61            result = android_fx_statusToResult(status);
62        }
63#endif
64        interface_unlock_exclusive(thiz);
65    }
66
67    SL_LEAVE_INTERFACE
68}
69
70
71static SLresult IEnvironmentalReverb_GetRoomLevel(SLEnvironmentalReverbItf self, SLmillibel *pRoom)
72{
73    SL_ENTER_INTERFACE
74
75    if (NULL == pRoom) {
76        result = SL_RESULT_PARAMETER_INVALID;
77    } else {
78        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
79        interface_lock_shared(thiz);
80#if 1 // !defined(ANDROID)
81        result = SL_RESULT_SUCCESS;
82#else
83        if (NO_ENVREVERB(thiz)) {
84            result = SL_RESULT_CONTROL_LOST;
85        } else {
86            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
87                    REVERB_PARAM_ROOM_LEVEL, &thiz->mProperties.roomLevel);
88            result = android_fx_statusToResult(status);
89        }
90#endif
91        *pRoom = thiz->mProperties.roomLevel;
92
93        interface_unlock_shared(thiz);
94
95    }
96
97    SL_LEAVE_INTERFACE
98}
99
100
101static SLresult IEnvironmentalReverb_SetRoomHFLevel(
102    SLEnvironmentalReverbItf self, SLmillibel roomHF)
103{
104    SL_ENTER_INTERFACE
105
106    //if (!(SL_MILLIBEL_MIN <= roomHF && roomHF <= 0)) {
107    // comparison (SL_MILLIBEL_MIN <= roomHF) is always true due to range of SLmillibel
108    if (!(roomHF <= 0)) {
109        result = SL_RESULT_PARAMETER_INVALID;
110    } else {
111        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
112        interface_lock_exclusive(thiz);
113        thiz->mProperties.roomHFLevel = roomHF;
114#if !defined(ANDROID)
115        result = SL_RESULT_SUCCESS;
116#else
117        if (NO_ENVREVERB(thiz)) {
118            result = SL_RESULT_CONTROL_LOST;
119        } else {
120            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
121                    REVERB_PARAM_ROOM_HF_LEVEL, &roomHF);
122            result = android_fx_statusToResult(status);
123        }
124#endif
125        interface_unlock_exclusive(thiz);
126    }
127
128    SL_LEAVE_INTERFACE
129}
130
131
132static SLresult IEnvironmentalReverb_GetRoomHFLevel(
133    SLEnvironmentalReverbItf self, SLmillibel *pRoomHF)
134{
135    SL_ENTER_INTERFACE
136
137    if (NULL == pRoomHF) {
138        result = SL_RESULT_PARAMETER_INVALID;
139    } else {
140        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
141        interface_lock_shared(thiz);
142#if 1 // !defined(ANDROID)
143        result = SL_RESULT_SUCCESS;
144#else
145        if (NO_ENVREVERB(thiz)) {
146            result = SL_RESULT_CONTROL_LOST;
147        } else {
148            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
149                    REVERB_PARAM_ROOM_HF_LEVEL, &thiz->mProperties.roomHFLevel);
150            result = android_fx_statusToResult(status);
151        }
152#endif
153        *pRoomHF = thiz->mProperties.roomHFLevel;
154
155        interface_unlock_shared(thiz);
156    }
157
158    SL_LEAVE_INTERFACE
159}
160
161
162static SLresult IEnvironmentalReverb_SetDecayTime(
163    SLEnvironmentalReverbItf self, SLmillisecond decayTime)
164{
165    SL_ENTER_INTERFACE
166
167    if (!(100 <= decayTime && decayTime <= 20000)) {
168        result = SL_RESULT_PARAMETER_INVALID;
169    } else {
170        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
171        interface_lock_exclusive(thiz);
172        thiz->mProperties.decayTime = decayTime;
173#if 1 // !defined(ANDROID)
174        result = SL_RESULT_SUCCESS;
175#else
176        if (NO_ENVREVERB(thiz)) {
177            result = SL_RESULT_CONTROL_LOST;
178        } else {
179            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
180                    REVERB_PARAM_DECAY_TIME, &decayTime);
181            result = android_fx_statusToResult(status);
182        }
183#endif
184        interface_unlock_exclusive(thiz);
185    }
186
187    SL_LEAVE_INTERFACE
188}
189
190
191static SLresult IEnvironmentalReverb_GetDecayTime(
192    SLEnvironmentalReverbItf self, SLmillisecond *pDecayTime)
193{
194    SL_ENTER_INTERFACE
195
196    if (NULL == pDecayTime) {
197        result = SL_RESULT_PARAMETER_INVALID;
198    } else {
199        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
200        interface_lock_shared(thiz);
201#if 1 // !defined(ANDROID)
202        result = SL_RESULT_SUCCESS;
203#else
204        if (NO_ENVREVERB(thiz)) {
205            result = SL_RESULT_CONTROL_LOST;
206        } else {
207            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
208                    REVERB_PARAM_DECAY_TIME, &thiz->mProperties.decayTime);
209            result = android_fx_statusToResult(status);
210        }
211#endif
212        *pDecayTime = thiz->mProperties.decayTime;
213
214        interface_unlock_shared(thiz);
215    }
216
217    SL_LEAVE_INTERFACE
218}
219
220
221static SLresult IEnvironmentalReverb_SetDecayHFRatio(
222    SLEnvironmentalReverbItf self, SLpermille decayHFRatio)
223{
224    SL_ENTER_INTERFACE
225
226    if (!(100 <= decayHFRatio && decayHFRatio <= 2000)) {
227        result = SL_RESULT_PARAMETER_INVALID;
228    } else {
229        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
230        interface_lock_exclusive(thiz);
231        thiz->mProperties.decayHFRatio = decayHFRatio;
232#if !defined(ANDROID)
233        result = SL_RESULT_SUCCESS;
234#else
235        if (NO_ENVREVERB(thiz)) {
236            result = SL_RESULT_CONTROL_LOST;
237        } else {
238            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
239                    REVERB_PARAM_DECAY_HF_RATIO, &decayHFRatio);
240            result = android_fx_statusToResult(status);
241        }
242#endif
243        interface_unlock_exclusive(thiz);
244    }
245
246    SL_LEAVE_INTERFACE
247}
248
249
250static SLresult IEnvironmentalReverb_GetDecayHFRatio(
251    SLEnvironmentalReverbItf self, SLpermille *pDecayHFRatio)
252{
253    SL_ENTER_INTERFACE
254
255    if (NULL == pDecayHFRatio) {
256        result = SL_RESULT_PARAMETER_INVALID;
257    } else {
258        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
259        interface_lock_shared(thiz);
260#if 1 // !defined(ANDROID)
261        result = SL_RESULT_SUCCESS;
262#else
263        if (NO_ENVREVERB(thiz)) {
264            result = SL_RESULT_CONTROL_LOST;
265        } else {
266            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
267                    REVERB_PARAM_DECAY_HF_RATIO, &thiz->mProperties.decayHFRatio);
268            result = android_fx_statusToResult(status);
269        }
270#endif
271        *pDecayHFRatio = thiz->mProperties.decayHFRatio;
272
273        interface_unlock_shared(thiz);
274    }
275
276    SL_LEAVE_INTERFACE
277}
278
279
280static SLresult IEnvironmentalReverb_SetReflectionsLevel(
281    SLEnvironmentalReverbItf self, SLmillibel reflectionsLevel)
282{
283    SL_ENTER_INTERFACE
284
285    //if (!(SL_MILLIBEL_MIN <= reflectionsLevel && reflectionsLevel <= 1000)) {
286    // comparison (SL_MILLIBEL_MIN <= reflectionsLevel) is always true due to range of SLmillibel
287    if (!(reflectionsLevel <= 1000)) {
288        result = SL_RESULT_PARAMETER_INVALID;
289    } else {
290        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
291        interface_lock_exclusive(thiz);
292        thiz->mProperties.reflectionsLevel = reflectionsLevel;
293#if !defined(ANDROID)
294        result = SL_RESULT_SUCCESS;
295#else
296        if (NO_ENVREVERB(thiz)) {
297            result = SL_RESULT_CONTROL_LOST;
298        } else {
299            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
300                    REVERB_PARAM_REFLECTIONS_LEVEL, &reflectionsLevel);
301            result = android_fx_statusToResult(status);
302        }
303#endif
304        interface_unlock_exclusive(thiz);
305    }
306
307    SL_LEAVE_INTERFACE
308}
309
310
311static SLresult IEnvironmentalReverb_GetReflectionsLevel(
312    SLEnvironmentalReverbItf self, SLmillibel *pReflectionsLevel)
313{
314    SL_ENTER_INTERFACE
315
316    if (NULL == pReflectionsLevel) {
317        result = SL_RESULT_PARAMETER_INVALID;
318    } else {
319        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
320        interface_lock_shared(thiz);
321#if 1 // !defined(ANDROID)
322        result = SL_RESULT_SUCCESS;
323#else
324        if (NO_ENVREVERB(thiz)) {
325            result = SL_RESULT_CONTROL_LOST;
326        } else {
327            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
328                    REVERB_PARAM_REFLECTIONS_LEVEL, &thiz->mProperties.reflectionsLevel);
329            result = android_fx_statusToResult(status);
330        }
331#endif
332        *pReflectionsLevel = thiz->mProperties.reflectionsLevel;
333
334        interface_unlock_shared(thiz);
335    }
336
337    SL_LEAVE_INTERFACE
338}
339
340
341static SLresult IEnvironmentalReverb_SetReflectionsDelay(
342    SLEnvironmentalReverbItf self, SLmillisecond reflectionsDelay)
343{
344    SL_ENTER_INTERFACE
345
346    if (!(/* 0 <= reflectionsDelay && */ reflectionsDelay <= 300)) {
347        result = SL_RESULT_PARAMETER_INVALID;
348    } else {
349        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
350        interface_lock_exclusive(thiz);
351        thiz->mProperties.reflectionsDelay = reflectionsDelay;
352#if !defined(ANDROID)
353        result = SL_RESULT_SUCCESS;
354#else
355        if (NO_ENVREVERB(thiz)) {
356            result = SL_RESULT_CONTROL_LOST;
357        } else {
358            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
359                    REVERB_PARAM_REFLECTIONS_DELAY, &reflectionsDelay);
360            result = android_fx_statusToResult(status);
361        }
362#endif
363        interface_unlock_exclusive(thiz);
364    }
365
366    SL_LEAVE_INTERFACE
367}
368
369
370static SLresult IEnvironmentalReverb_GetReflectionsDelay(
371    SLEnvironmentalReverbItf self, SLmillisecond *pReflectionsDelay)
372{
373    SL_ENTER_INTERFACE
374
375    if (NULL == pReflectionsDelay) {
376        result = SL_RESULT_PARAMETER_INVALID;
377    } else {
378        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
379        interface_lock_shared(thiz);
380#if 1 // !defined(ANDROID)
381        result = SL_RESULT_SUCCESS;
382#else
383        if (NO_ENVREVERB(thiz)) {
384            result = SL_RESULT_CONTROL_LOST;
385        } else {
386            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
387                    REVERB_PARAM_REFLECTIONS_DELAY, &thiz->mProperties.reflectionsDelay);
388            result = android_fx_statusToResult(status);
389        }
390#endif
391        *pReflectionsDelay = thiz->mProperties.reflectionsDelay;
392
393        interface_unlock_shared(thiz);
394    }
395
396    SL_LEAVE_INTERFACE
397}
398
399
400static SLresult IEnvironmentalReverb_SetReverbLevel(
401    SLEnvironmentalReverbItf self, SLmillibel reverbLevel)
402{
403    SL_ENTER_INTERFACE
404
405    //if (!(SL_MILLIBEL_MIN <= reverbLevel && reverbLevel <= 2000)) {
406    // comparison (SL_MILLIBEL_MIN <= reverbLevel) is always true due to range of SLmillibel
407    if (!(reverbLevel <= 2000)) {
408        result = SL_RESULT_PARAMETER_INVALID;
409    } else {
410        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
411        interface_lock_exclusive(thiz);
412        thiz->mProperties.reverbLevel = reverbLevel;
413#if !defined(ANDROID)
414        result = SL_RESULT_SUCCESS;
415#else
416        if (NO_ENVREVERB(thiz)) {
417            result = SL_RESULT_CONTROL_LOST;
418        } else {
419            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
420                    REVERB_PARAM_REVERB_LEVEL, &reverbLevel);
421            result = android_fx_statusToResult(status);
422        }
423#endif
424        interface_unlock_exclusive(thiz);
425    }
426
427    SL_LEAVE_INTERFACE
428}
429
430
431static SLresult IEnvironmentalReverb_GetReverbLevel(
432    SLEnvironmentalReverbItf self, SLmillibel *pReverbLevel)
433{
434    SL_ENTER_INTERFACE
435
436    if (NULL == pReverbLevel) {
437        result = SL_RESULT_PARAMETER_INVALID;
438    } else {
439        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
440        interface_lock_shared(thiz);
441#if 1 // !defined(ANDROID)
442        result = SL_RESULT_SUCCESS;
443#else
444        if (NO_ENVREVERB(thiz)) {
445            result = SL_RESULT_CONTROL_LOST;
446        } else {
447            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
448                    REVERB_PARAM_REVERB_LEVEL, &thiz->mProperties.reverbLevel);
449            result = android_fx_statusToResult(status);
450        }
451#endif
452        *pReverbLevel = thiz->mProperties.reverbLevel;
453
454        interface_unlock_shared(thiz);
455    }
456
457    SL_LEAVE_INTERFACE
458}
459
460
461static SLresult IEnvironmentalReverb_SetReverbDelay(
462    SLEnvironmentalReverbItf self, SLmillisecond reverbDelay)
463{
464    SL_ENTER_INTERFACE
465
466    if (!(/* 0 <= reverbDelay && */ reverbDelay <= 100)) {
467        result = SL_RESULT_PARAMETER_INVALID;
468    } else {
469        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
470        interface_lock_exclusive(thiz);
471        thiz->mProperties.reverbDelay = reverbDelay;
472#if !defined(ANDROID)
473        result = SL_RESULT_SUCCESS;
474#else
475        if (NO_ENVREVERB(thiz)) {
476            result = SL_RESULT_CONTROL_LOST;
477        } else {
478            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
479                    REVERB_PARAM_REVERB_DELAY, &reverbDelay);
480            result = android_fx_statusToResult(status);
481        }
482#endif
483        interface_unlock_exclusive(thiz);
484    }
485
486    SL_LEAVE_INTERFACE
487}
488
489
490static SLresult IEnvironmentalReverb_GetReverbDelay(
491    SLEnvironmentalReverbItf self, SLmillisecond *pReverbDelay)
492{
493    SL_ENTER_INTERFACE
494
495    if (NULL == pReverbDelay) {
496        result = SL_RESULT_PARAMETER_INVALID;
497    } else {
498        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
499        interface_lock_shared(thiz);
500#if 1 // !defined(ANDROID)
501        result = SL_RESULT_SUCCESS;
502#else
503        if (NO_ENVREVERB(thiz)) {
504            result = SL_RESULT_CONTROL_LOST;
505        } else {
506            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
507                    REVERB_PARAM_REVERB_DELAY, &thiz->mProperties.reverbDelay);
508            result = android_fx_statusToResult(status);
509        }
510#endif
511        *pReverbDelay = thiz->mProperties.reverbDelay;
512
513        interface_unlock_shared(thiz);
514    }
515
516    SL_LEAVE_INTERFACE
517}
518
519
520static SLresult IEnvironmentalReverb_SetDiffusion(
521    SLEnvironmentalReverbItf self, SLpermille diffusion)
522{
523    SL_ENTER_INTERFACE
524
525    if (!(0 <= diffusion && diffusion <= 1000)) {
526        result = SL_RESULT_PARAMETER_INVALID;
527    } else {
528        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
529        interface_lock_exclusive(thiz);
530        thiz->mProperties.diffusion = diffusion;
531#if !defined(ANDROID)
532        result = SL_RESULT_SUCCESS;
533#else
534        if (NO_ENVREVERB(thiz)) {
535            result = SL_RESULT_CONTROL_LOST;
536        } else {
537            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
538                    REVERB_PARAM_DIFFUSION, &diffusion);
539            result = android_fx_statusToResult(status);
540        }
541#endif
542        interface_unlock_exclusive(thiz);
543    }
544
545    SL_LEAVE_INTERFACE
546}
547
548
549static SLresult IEnvironmentalReverb_GetDiffusion(SLEnvironmentalReverbItf self,
550     SLpermille *pDiffusion)
551{
552    SL_ENTER_INTERFACE
553
554    if (NULL == pDiffusion) {
555        result = SL_RESULT_PARAMETER_INVALID;
556    } else {
557        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
558        interface_lock_shared(thiz);
559#if 1 // !defined(ANDROID)
560        result = SL_RESULT_SUCCESS;
561#else
562        if (NO_ENVREVERB(thiz)) {
563            result = SL_RESULT_CONTROL_LOST;
564        } else {
565            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
566                    REVERB_PARAM_DIFFUSION, &thiz->mProperties.diffusion);
567            result = android_fx_statusToResult(status);
568        }
569#endif
570        *pDiffusion = thiz->mProperties.diffusion;
571
572        interface_unlock_shared(thiz);
573    }
574
575    SL_LEAVE_INTERFACE
576}
577
578
579static SLresult IEnvironmentalReverb_SetDensity(SLEnvironmentalReverbItf self,
580    SLpermille density)
581{
582    SL_ENTER_INTERFACE
583
584    if (!(0 <= density && density <= 1000)) {
585        result = SL_RESULT_PARAMETER_INVALID;
586    } else {
587        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
588        interface_lock_exclusive(thiz);
589        thiz->mProperties.density = density;
590#if !defined(ANDROID)
591        result = SL_RESULT_SUCCESS;
592#else
593        if (NO_ENVREVERB(thiz)) {
594            result = SL_RESULT_CONTROL_LOST;
595        } else {
596            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
597                    REVERB_PARAM_DENSITY, &density);
598            result = android_fx_statusToResult(status);
599        }
600#endif
601        interface_unlock_exclusive(thiz);
602    }
603
604    SL_LEAVE_INTERFACE
605}
606
607
608static SLresult IEnvironmentalReverb_GetDensity(SLEnvironmentalReverbItf self,
609    SLpermille *pDensity)
610{
611    SL_ENTER_INTERFACE
612
613    if (NULL == pDensity) {
614        result = SL_RESULT_PARAMETER_INVALID;
615    } else {
616        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
617        interface_lock_shared(thiz);
618#if 1 // !defined(ANDROID)
619        result = SL_RESULT_SUCCESS;
620#else
621        if (NO_ENVREVERB(thiz)) {
622            result = SL_RESULT_CONTROL_LOST;
623        } else {
624            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
625                    REVERB_PARAM_DENSITY, &thiz->mProperties.density);
626            result = android_fx_statusToResult(status);
627        }
628#endif
629        *pDensity = thiz->mProperties.density;
630
631        interface_unlock_shared(thiz);
632    }
633
634    SL_LEAVE_INTERFACE
635}
636
637
638static SLresult IEnvironmentalReverb_SetEnvironmentalReverbProperties(SLEnvironmentalReverbItf self,
639    const SLEnvironmentalReverbSettings *pProperties)
640{
641    SL_ENTER_INTERFACE
642
643    // note that it's unnecessary to verify that any level stored inside the "properties" struct
644    //  is >= SL_MILLIBEL_MIN before using it, due to range of SLmillibel
645
646    result = SL_RESULT_PARAMETER_INVALID;
647    do {
648        if (NULL == pProperties)
649            break;
650        SLEnvironmentalReverbSettings properties = *pProperties;
651        if (!(properties.roomLevel <= 0))
652            break;
653        if (!(properties.roomHFLevel <= 0))
654            break;
655        if (!(100 <= properties.decayTime && properties.decayTime <= 20000))
656            break;
657        if (!(100 <= properties.decayHFRatio && properties.decayHFRatio <= 2000))
658            break;
659        if (!(properties.reflectionsLevel <= 1000))
660            break;
661        if (!(/* 0 <= properties.reflectionsDelay && */ properties.reflectionsDelay <= 300))
662            break;
663        if (!(properties.reverbLevel <= 2000))
664            break;
665        if (!(/* 0 <= properties.reverbDelay && */ properties.reverbDelay <= 100))
666            break;
667        if (!(0 <= properties.diffusion && properties.diffusion <= 1000))
668            break;
669        if (!(0 <= properties.density && properties.density <= 1000))
670            break;
671        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
672        interface_lock_exclusive(thiz);
673        thiz->mProperties = properties;
674#if !defined(ANDROID)
675        result = SL_RESULT_SUCCESS;
676#else
677        if (NO_ENVREVERB(thiz)) {
678            result = SL_RESULT_CONTROL_LOST;
679        } else {
680            android::status_t status = android_erev_setParam(thiz->mEnvironmentalReverbEffect,
681                    REVERB_PARAM_PROPERTIES, &properties);
682            result = android_fx_statusToResult(status);
683        }
684#endif
685        interface_unlock_exclusive(thiz);
686    } while (0);
687
688    SL_LEAVE_INTERFACE
689}
690
691
692static SLresult IEnvironmentalReverb_GetEnvironmentalReverbProperties(
693    SLEnvironmentalReverbItf self, SLEnvironmentalReverbSettings *pProperties)
694{
695    SL_ENTER_INTERFACE
696
697    if (NULL == pProperties) {
698        result = SL_RESULT_PARAMETER_INVALID;
699    } else {
700        IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
701        interface_lock_shared(thiz);
702#if 1 // !defined(ANDROID)
703        result = SL_RESULT_SUCCESS;
704#else
705        if (NO_ENVREVERB(thiz)) {
706            result = SL_RESULT_CONTROL_LOST;
707        } else {
708            android::status_t status = android_erev_getParam(thiz->mEnvironmentalReverbEffect,
709                    REVERB_PARAM_PROPERTIES, &thiz->mProperties);
710            result = android_fx_statusToResult(status);
711        }
712#endif
713        *pProperties = thiz->mProperties;
714
715        interface_unlock_shared(thiz);
716    }
717
718    SL_LEAVE_INTERFACE
719}
720
721
722static const struct SLEnvironmentalReverbItf_ IEnvironmentalReverb_Itf = {
723    IEnvironmentalReverb_SetRoomLevel,
724    IEnvironmentalReverb_GetRoomLevel,
725    IEnvironmentalReverb_SetRoomHFLevel,
726    IEnvironmentalReverb_GetRoomHFLevel,
727    IEnvironmentalReverb_SetDecayTime,
728    IEnvironmentalReverb_GetDecayTime,
729    IEnvironmentalReverb_SetDecayHFRatio,
730    IEnvironmentalReverb_GetDecayHFRatio,
731    IEnvironmentalReverb_SetReflectionsLevel,
732    IEnvironmentalReverb_GetReflectionsLevel,
733    IEnvironmentalReverb_SetReflectionsDelay,
734    IEnvironmentalReverb_GetReflectionsDelay,
735    IEnvironmentalReverb_SetReverbLevel,
736    IEnvironmentalReverb_GetReverbLevel,
737    IEnvironmentalReverb_SetReverbDelay,
738    IEnvironmentalReverb_GetReverbDelay,
739    IEnvironmentalReverb_SetDiffusion,
740    IEnvironmentalReverb_GetDiffusion,
741    IEnvironmentalReverb_SetDensity,
742    IEnvironmentalReverb_GetDensity,
743    IEnvironmentalReverb_SetEnvironmentalReverbProperties,
744    IEnvironmentalReverb_GetEnvironmentalReverbProperties
745};
746
747static const SLEnvironmentalReverbSettings IEnvironmentalReverb_default = {
748    SL_MILLIBEL_MIN, // roomLevel
749    0,               // roomHFLevel
750    1000,            // decayTime
751    500,             // decayHFRatio
752    SL_MILLIBEL_MIN, // reflectionsLevel
753    20,              // reflectionsDelay
754    SL_MILLIBEL_MIN, // reverbLevel
755    40,              // reverbDelay
756    1000,            // diffusion
757    1000             // density
758};
759
760void IEnvironmentalReverb_init(void *self)
761{
762    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
763    thiz->mItf = &IEnvironmentalReverb_Itf;
764    thiz->mProperties = IEnvironmentalReverb_default;
765#if defined(ANDROID)
766    memset(&thiz->mEnvironmentalReverbDescriptor, 0, sizeof(effect_descriptor_t));
767    // placement new (explicit constructor)
768    (void) new (&thiz->mEnvironmentalReverbEffect) android::sp<android::AudioEffect>();
769#endif
770}
771
772void IEnvironmentalReverb_deinit(void *self)
773{
774#if defined(ANDROID)
775    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
776    // explicit destructor
777    thiz->mEnvironmentalReverbEffect.~sp();
778#endif
779}
780
781bool IEnvironmentalReverb_Expose(void *self)
782{
783#if defined(ANDROID)
784    IEnvironmentalReverb *thiz = (IEnvironmentalReverb *) self;
785    if (!android_fx_initEffectDescriptor(SL_IID_ENVIRONMENTALREVERB,
786            &thiz->mEnvironmentalReverbDescriptor)) {
787        SL_LOGE("EnvironmentalReverb initialization failed.");
788        return false;
789    }
790#endif
791    return true;
792}
793