blob: 4ba94255592e3cf91653ac45285bdbd894a75ad8 [file] [log] [blame]
Hyundo Moon660a74e2017-12-13 11:29:45 +09001/*
2 * Copyright 2018 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#define LOG_TAG "JAudioTrack"
18
19#include "media/JAudioAttributes.h"
20#include "media/JAudioFormat.h"
21#include "media/JAudioTrack.h"
22
23#include <android_runtime/AndroidRuntime.h>
24#include <media/AudioResamplerPublic.h>
25
26namespace android {
27
28// TODO: Add NULL && Exception checks after every JNI call.
29JAudioTrack::JAudioTrack( // < Usages of the arguments are below >
30 audio_stream_type_t streamType, // AudioAudioAttributes
31 uint32_t sampleRate, // AudioFormat && bufferSizeInBytes
32 audio_format_t format, // AudioFormat && bufferSizeInBytes
33 audio_channel_mask_t channelMask, // AudioFormat && bufferSizeInBytes
34 size_t frameCount, // bufferSizeInBytes
35 audio_session_t sessionId, // AudioTrack
36 const audio_attributes_t* pAttributes, // AudioAttributes
37 float maxRequiredSpeed) { // bufferSizeInBytes
38
39 JNIEnv *env = AndroidRuntime::getJNIEnv();
40 jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack");
41
42 maxRequiredSpeed = std::min(std::max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
43
44 int bufferSizeInBytes = 0;
45 if (sampleRate == 0 || frameCount > 0) {
46 // Manually calculate buffer size.
47 bufferSizeInBytes = audio_channel_count_from_out_mask(channelMask)
48 * audio_bytes_per_sample(format) * (frameCount > 0 ? frameCount : 1);
49 } else if (sampleRate > 0) {
50 // Call Java AudioTrack::getMinBufferSize().
51 jmethodID jGetMinBufferSize =
52 env->GetStaticMethodID(jAudioTrackCls, "getMinBufferSize", "(III)I");
53 bufferSizeInBytes = env->CallStaticIntMethod(jAudioTrackCls, jGetMinBufferSize,
54 sampleRate, outChannelMaskFromNative(channelMask), audioFormatFromNative(format));
55 }
56 bufferSizeInBytes = (int) (bufferSizeInBytes * maxRequiredSpeed);
57
58 // Create a Java AudioTrack object through its Builder.
59 jclass jBuilderCls = env->FindClass("android/media/AudioTrack$Builder");
60 jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
61 jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
62
63 jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes",
64 "(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;");
65 jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes,
66 JAudioAttributes::createAudioAttributesObj(env, pAttributes, streamType));
67
68 jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat",
69 "(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;");
70 jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioFormat,
71 JAudioFormat::createAudioFormatObj(env, sampleRate, format, channelMask));
72
73 jmethodID jSetBufferSizeInBytes = env->GetMethodID(jBuilderCls, "setBufferSizeInBytes",
74 "(I)Landroid/media/AudioTrack$Builder;");
75 jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetBufferSizeInBytes, bufferSizeInBytes);
76
77 // We only use streaming mode of Java AudioTrack.
78 jfieldID jModeStream = env->GetStaticFieldID(jAudioTrackCls, "MODE_STREAM", "I");
79 jint transferMode = env->GetStaticIntField(jAudioTrackCls, jModeStream);
80 jmethodID jSetTransferMode = env->GetMethodID(jBuilderCls, "setTransferMode",
81 "(I)Landroid/media/AudioTrack$Builder;");
82 jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetTransferMode,
83 transferMode /* Java AudioTrack::MODE_STREAM */);
84
85 if (sessionId != 0) {
86 jmethodID jSetSessionId = env->GetMethodID(jBuilderCls, "setSessionId",
87 "(I)Landroid/media/AudioTrack$Builder;");
88 jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetSessionId, sessionId);
89 }
90
91 jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioTrack;");
92 mAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild);
93}
94
95void JAudioTrack::stop() {
96 JNIEnv *env = AndroidRuntime::getJNIEnv();
97 jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack");
98 jmethodID jStop = env->GetMethodID(jAudioTrackCls, "stop", "()V");
99 env->CallVoidMethod(mAudioTrackObj, jStop);
100}
101
102} // namespace android