1 /*
2  * Copyright (C) 2020 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 package android.media.musicrecognition;
18 
19 import static android.media.AudioAttributes.CONTENT_TYPE_MUSIC;
20 import static android.media.AudioFormat.ENCODING_PCM_16BIT;
21 
22 import static java.util.Objects.requireNonNull;
23 
24 import android.annotation.NonNull;
25 import android.annotation.SystemApi;
26 import android.media.AudioAttributes;
27 import android.media.AudioFormat;
28 import android.media.AudioRecord;
29 import android.media.MediaRecorder;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 
33 /**
34  * Encapsulates parameters for making music recognition queries via {@link MusicRecognitionManager}.
35  *
36  * @hide
37  */
38 @SystemApi
39 public final class RecognitionRequest implements Parcelable {
40     @NonNull private final AudioAttributes mAudioAttributes;
41     @NonNull private final AudioFormat mAudioFormat;
42     private final int mCaptureSession;
43     private final int mMaxAudioLengthSeconds;
44     private final int mIgnoreBeginningFrames;
45 
RecognitionRequest(Builder b)46     private RecognitionRequest(Builder b) {
47         mAudioAttributes = requireNonNull(b.mAudioAttributes);
48         mAudioFormat = requireNonNull(b.mAudioFormat);
49         mCaptureSession = b.mCaptureSession;
50         mMaxAudioLengthSeconds = b.mMaxAudioLengthSeconds;
51         mIgnoreBeginningFrames = b.mIgnoreBeginningFrames;
52     }
53 
54     @NonNull
getAudioAttributes()55     public AudioAttributes getAudioAttributes() {
56         return mAudioAttributes;
57     }
58 
59     @NonNull
getAudioFormat()60     public AudioFormat getAudioFormat() {
61         return mAudioFormat;
62     }
63 
getCaptureSession()64     public int getCaptureSession() {
65         return mCaptureSession;
66     }
67 
68     @SuppressWarnings("MethodNameUnits")
getMaxAudioLengthSeconds()69     public int getMaxAudioLengthSeconds() {
70         return mMaxAudioLengthSeconds;
71     }
72 
getIgnoreBeginningFrames()73     public int getIgnoreBeginningFrames() {
74         return mIgnoreBeginningFrames;
75     }
76 
77     /**
78      * Builder for constructing StreamSearchRequest objects.
79      *
80      * @hide
81      */
82     @SystemApi
83     public static final class Builder {
84         private AudioFormat mAudioFormat = new AudioFormat.Builder()
85                 .setSampleRate(16000)
86                 .setEncoding(ENCODING_PCM_16BIT)
87                 .build();
88         private AudioAttributes mAudioAttributes = new AudioAttributes.Builder()
89                 .setContentType(CONTENT_TYPE_MUSIC)
90                 .build();
91         private int mCaptureSession = MediaRecorder.AudioSource.MIC;
92         private int mMaxAudioLengthSeconds = 24; // Max enforced in system server.
93         private int mIgnoreBeginningFrames = 0;
94 
95         /** Attributes passed to the constructed {@link AudioRecord}. */
96         @NonNull
setAudioAttributes(@onNull AudioAttributes audioAttributes)97         public Builder setAudioAttributes(@NonNull AudioAttributes audioAttributes) {
98             mAudioAttributes = audioAttributes;
99             return this;
100         }
101 
102         /** AudioFormat passed to the constructed {@link AudioRecord}. */
103         @NonNull
setAudioFormat(@onNull AudioFormat audioFormat)104         public Builder setAudioFormat(@NonNull AudioFormat audioFormat) {
105             mAudioFormat = audioFormat;
106             return this;
107         }
108 
109         /** Constant from {@link android.media.MediaRecorder.AudioSource}. */
110         @NonNull
setCaptureSession(int captureSession)111         public Builder setCaptureSession(int captureSession) {
112             mCaptureSession = captureSession;
113             return this;
114         }
115 
116         /** Maximum number of seconds to stream from the audio source. */
117         @NonNull
setMaxAudioLengthSeconds(int maxAudioLengthSeconds)118         public Builder setMaxAudioLengthSeconds(int maxAudioLengthSeconds) {
119             mMaxAudioLengthSeconds = maxAudioLengthSeconds;
120             return this;
121         }
122 
123         /**
124          * Number of frames to drop from the start of the stream
125          * (if recording is PCM stereo, one frame is two samples).
126          **/
127         @NonNull
setIgnoreBeginningFrames(int ignoreBeginningFrames)128         public Builder setIgnoreBeginningFrames(int ignoreBeginningFrames) {
129             mIgnoreBeginningFrames = ignoreBeginningFrames;
130             return this;
131         }
132 
133         /** Returns the constructed request. */
134         @NonNull
build()135         public RecognitionRequest build() {
136             return new RecognitionRequest(this);
137         }
138     }
139 
140     @Override
describeContents()141     public int describeContents() {
142         return 0;
143     }
144 
145     @Override
writeToParcel(@onNull Parcel dest, int flags)146     public void writeToParcel(@NonNull Parcel dest, int flags) {
147         dest.writeParcelable(mAudioFormat, flags);
148         dest.writeParcelable(mAudioAttributes, flags);
149         dest.writeInt(mCaptureSession);
150         dest.writeInt(mMaxAudioLengthSeconds);
151         dest.writeInt(mIgnoreBeginningFrames);
152     }
153 
RecognitionRequest(Parcel in)154     private RecognitionRequest(Parcel in) {
155         mAudioFormat = in.readParcelable(AudioFormat.class.getClassLoader());
156         mAudioAttributes = in.readParcelable(AudioAttributes.class.getClassLoader());
157         mCaptureSession = in.readInt();
158         mMaxAudioLengthSeconds = in.readInt();
159         mIgnoreBeginningFrames = in.readInt();
160     }
161 
162     @NonNull public static final Creator<RecognitionRequest> CREATOR =
163             new Creator<RecognitionRequest>() {
164 
165         @Override
166         public RecognitionRequest createFromParcel(Parcel p) {
167             return new RecognitionRequest(p);
168         }
169 
170         @Override
171         public RecognitionRequest[] newArray(int size) {
172             return new RecognitionRequest[size];
173         }
174     };
175 }
176