質問編集履歴

2

プログラムを「ボタンを押したら録音を開始, もう一度押したら停止」となるように変更しました。またその過程で、言語を「Kotlin」から「Java」へと変更しました。

2019/04/16 04:12

投稿

oto.
oto.

スコア10

test CHANGED
File without changes
test CHANGED
@@ -2,25 +2,35 @@
2
2
 
3
3
 
4
4
 
5
- 現在、androidstudio(Kotlin)にてAudioRecordで音を録り、音の大きさに応じて
5
+ 現在、androidstudioにてAudioRecordで音を録り、音の大きさに応じて
6
6
 
7
7
  アプリ画面全体の色をリアルタイムに変えるというアプリを作りたいと思っています。
8
8
 
9
+ 言語はKotlinを想定していましたが、情報を集めきれず、Javaに路線変更いたしました。
10
+
9
11
 
10
12
 
11
13
  色は五段階程度を想定しております。
12
14
 
13
15
 
14
16
 
15
-
16
-
17
- AudioRecord中のLog.vの内容を
18
-
19
- 何かのビューに出力れば良いかと
17
+ 「録音」と表示されたボタンを押
18
+
20
-
19
+
20
+
21
+ 録音を開始し、ボタンの表示が「停止」になる
22
+
23
+
24
+
25
+ 「停止」と表示されたボタンを押すと、録音は停止し、ファイル名「sample.3gp」にて音声が保存される。
26
+
21
- 思ってるのですが、具体的どのようにすればよいかわからず
27
+ うプログラムをJavaて(見よう見まねで)作成しました。
28
+
22
-
29
+ しかし、「音量のログを表示する」「そのログを用いて画面を変化させる」という作業が
30
+
23
- っておりま
31
+ どのように記せばよいかわかっておりません…
32
+
33
+ 具体的にどのような処理をすればログを取得(あるいは表示)することができるのでしょう…。
24
34
 
25
35
  ご教示いただけないでしょうか。
26
36
 
@@ -32,9 +42,15 @@
32
42
 
33
43
 
34
44
 
45
+ 「録音」と表示されたボタンを押す
46
+
47
+
48
+
49
+ 録音を開始し、ボタンの表示が「停止」になる
50
+
51
+
52
+
35
- デモンストレーションして「画面表示された『開始』ボタンを押すと、『運勢』という文字『大吉』に変わ」というプログラムを書きました
53
+ 「停止」と表示されたボタンを押すと、録音は停止し、ファイル名「sample.3gp」にて音声保存される。
36
-
37
- そこに AudioRecordクラスを追加し、改造していきたいと思っております。
38
54
 
39
55
 
40
56
 
@@ -44,209 +60,129 @@
44
60
 
45
61
 
46
62
 
47
- package com.example.myapplication
63
+ package com.example.test_recorder0415;
48
-
49
-
50
-
64
+
65
+
66
+
51
- import android.support.v7.app.AppCompatActivity
67
+ import android.support.v7.app.AppCompatActivity;
52
-
68
+
53
- import android.os.Bundle
69
+ import android.os.Bundle;
70
+
54
-
71
+ import java.io.IOException;
72
+
55
- import android.view.View
73
+ import android.app. Activity;
56
-
57
- import kotlinx.android.synthetic.main.activity_main.*
74
+
58
-
59
- import android.media.AudioFormat
60
-
61
- import android.media.AudioRecord
62
-
63
- import android.media.MediaRecorder
75
+ import android.media.MediaRecorder;
76
+
64
-
77
+ import android.os.Bundle;
78
+
65
- import android.util.Log
79
+ import android.view.Menu;
66
-
80
+
67
- import kotlin.math.max
81
+ import android.view.View;
82
+
68
-
83
+ import android.widget. Button;
69
-
70
-
71
-
72
-
84
+
85
+
86
+
87
+
88
+
73
- class MainActivity : AppCompatActivity() {
89
+ public class MainActivity extends AppCompatActivity {
90
+
91
+
92
+
74
-
93
+ private MediaRecorder rec;
94
+
75
-
95
+ boolean isRec= false; //G, 中カどうか
96
+
76
-
97
+ @Override
98
+
77
- override fun onCreate(savedInstanceState: Bundle?) {
99
+ public void onCreate(Bundle savedInstanceState) {
78
-
100
+
79
- super.onCreate(savedInstanceState)
101
+ super.onCreate(savedInstanceState);
80
-
102
+
81
- setContentView(R.layout.activity_main)
103
+ setContentView(R. layout.activity_main);
104
+
105
+ // MediaRecorderオブジェクトを準備
106
+
107
+ rec=new MediaRecorder();
82
108
 
83
109
  }
84
110
 
85
-
111
+ // [録音]/. [停止]ボタンがクリックされた時の処理
86
-
87
-
88
-
112
+
89
- fun onButton(v: View) {
113
+ public void onClick(View view) {
114
+
90
-
115
+ Button btnRecord = (Button) findViewById(R.id.btnRecord);
116
+
117
+
118
+
119
+ //録音停止中の場合
120
+
121
+
122
+
123
+ if (!isRec) {
124
+
125
+ // MediaRecorderオブジェクトの準備
126
+
127
+ rec.setAudioSource(MediaRecorder.AudioSource.MIC);
128
+
129
+ rec.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
130
+
131
+ rec.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
132
+
133
+ rec.setOutputFile("/mnt/sdcard/sample.3gp");
134
+
135
+ try {
136
+
137
+ rec.prepare();
138
+
139
+ } catch (IllegalStateException e) {
140
+
141
+ e.printStackTrace();
142
+
143
+ } catch (IOException e) {
144
+
145
+ e.printStackTrace();
146
+
147
+ }
148
+
149
+ //録音開始
150
+
151
+
152
+
153
+ rec.start();
154
+
155
+ isRec = true;
156
+
91
- tv.text = "大吉"
157
+ btnRecord.setText("停止");
158
+
159
+
160
+
161
+ //録音中の場合、録音を停止
162
+
163
+ } else {
164
+
165
+
166
+
167
+ rec.stop();
168
+
169
+ rec.reset();
170
+
171
+ isRec = false;
172
+
173
+ btnRecord.setText("録音");
174
+
175
+ }
92
176
 
93
177
  }
94
178
 
95
-
96
-
97
-
98
-
99
- /**
179
+ @Override
100
-
101
- * AudioRecord クラスのサンプルコード
180
+
102
-
103
- */
104
-
105
- class AudioRecordSample {
106
-
107
-
108
-
109
- // サンプリングレート (Hz)
110
-
111
- // 全デバイスサポート保障は44100のみ
112
-
113
- private val samplingRate = 44100
114
-
115
-
116
-
117
- // フレームレート (fps)
118
-
119
- // 1秒間に何回音声データを処理したいか
120
-
121
- // 各自好きに決める
122
-
123
- private val frameRate = 10
181
+ protected void onDestroy() {
124
-
125
-
126
-
127
- // 1フレームの音声データ(=Short値)の数
182
+
128
-
129
- private val oneFrameDataCount = samplingRate / frameRate
130
-
131
-
132
-
133
- // 1フレームの音声データのバイト数 (byte)
134
-
135
- // Byte = 8 bit, Short = 16 bit なので, Shortの倍になる
136
-
137
- private val oneFrameSizeInByte = oneFrameDataCount * 2
138
-
139
-
140
-
141
- // 音声データのバッファサイズ (byte)
142
-
143
- // 要件1:oneFrameSizeInByte より大きくする必要がある
144
-
145
- // 要件2:デバイスの要求する最小値より大きくする必要がある
146
-
147
- private val audioBufferSizeInByte =
148
-
149
- max(
150
-
151
- oneFrameSizeInByte * 10, // 適当に10フレーム分のバッファを持たせた
152
-
153
- android.media.AudioRecord.getMinBufferSize(
154
-
155
- samplingRate,
156
-
157
- AudioFormat.CHANNEL_IN_MONO,
158
-
159
- AudioFormat.ENCODING_PCM_16BIT
160
-
161
- )
162
-
163
- )
164
-
165
-
166
-
167
- fun startRecording() {
183
+ super.onDestroy();
168
-
169
-
170
-
171
- // インスタンスの作成
184
+
172
-
173
- val audioRecord = AudioRecord(
174
-
175
- MediaRecorder.AudioSource.MIC, // 音声のソース
176
-
177
- samplingRate, // サンプリングレート
178
-
179
- AudioFormat.CHANNEL_IN_MONO, // チャネル設定. MONO and STEREO が全デバイスサポート保障
180
-
181
- AudioFormat.ENCODING_PCM_16BIT, // PCM16が全デバイスサポート保障
182
-
183
- audioBufferSizeInByte
184
-
185
- ) // バッファ
186
-
187
-
188
-
189
- // 音声データを幾つずつ処理するか( = 1フレームのデータの数)
190
-
191
- audioRecord.positionNotificationPeriod = oneFrameDataCount
192
-
193
-
194
-
195
- // ここで指定した数になったタイミングで, 後続の onMarkerReached が呼び出される
196
-
197
- // 通常のストリーミング処理では必要なさそう?
198
-
199
- audioRecord.notificationMarkerPosition = 40000 // 使わないなら設定しない.
200
-
201
-
202
-
203
- // 音声データを格納する配列
204
-
205
- val audioDataArray = ShortArray(oneFrameDataCount)
206
-
207
-
208
-
209
- // コールバックを指定
210
-
211
- audioRecord.setRecordPositionUpdateListener(object : AudioRecord.OnRecordPositionUpdateListener {
212
-
213
-
214
-
215
- // フレームごとの処理
216
-
217
- override fun onPeriodicNotification(recorder: AudioRecord) {
218
-
219
- recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
220
-
221
- Log.v("AudioRecord", "onPeriodicNotification size=${audioDataArray.size}")
222
-
223
- // 好きに処理する
224
-
225
- }
226
-
227
-
228
-
229
- // マーカータイミングの処理.
230
-
231
- // notificationMarkerPosition に到達した際に呼ばれる
232
-
233
- override fun onMarkerReached(recorder: AudioRecord) {
234
-
235
- recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
236
-
237
- Log.v("AudioRecord", "onMarkerReached size=${audioDataArray.size}")
238
-
239
- // 好きに処理する
240
-
241
- }
242
-
243
- })
244
-
245
-
246
-
247
- audioRecord.startRecording()
185
+ rec.release();
248
-
249
- }
250
186
 
251
187
  }
252
188
 
@@ -258,53 +194,55 @@
258
194
 
259
195
  <?xml version="1.0" encoding="utf-8"?>
260
196
 
261
- <android.support.constraint.ConstraintLayout
197
+ <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
262
-
198
+
263
- xmlns:android="http://schemas.android.com/apk/res/android"
199
+ xmlns:app="http://schemas.android.com/apk/res-auto"
264
-
200
+
265
- xmlns:tools="http://schemas.android.com/tools"
201
+ xmlns:tools="http://schemas.android.com/tools"
202
+
266
-
203
+ android:layout_width="match_parent"
204
+
205
+ android:layout_height="match_parent"
206
+
207
+ tools:context=".MainActivity">
208
+
209
+
210
+
211
+ <TextView
212
+
213
+ android:layout_width="wrap_content"
214
+
215
+ android:layout_height="wrap_content"
216
+
217
+ android:text="Hello World!"
218
+
267
- xmlns:app="http://schemas.android.com/apk/res-auto"
219
+ app:layout_constraintBottom_toBottomOf="parent"
220
+
221
+ app:layout_constraintLeft_toLeftOf="parent"
222
+
223
+ app:layout_constraintRight_toRightOf="parent"
224
+
225
+ app:layout_constraintTop_toTopOf="parent" />
226
+
227
+
228
+
229
+ <Button
230
+
231
+ android:id="@+id/btnRecord"
268
232
 
269
233
  android:layout_width="match_parent"
270
234
 
271
- android:layout_height="match_parent"
272
-
273
- tools:context=".MainActivity">
274
-
275
-
276
-
277
- <TextView
278
-
279
- android:id="@+id/tv"
280
-
281
- android:layout_width="wrap_content"
282
-
283
- android:layout_height="wrap_content"
235
+ android:layout_height="wrap_content"
284
-
285
- android:text="今日の運勢"
236
+
286
-
287
- android:textSize="50sp"
288
-
289
- app:layout_constraintBottom_toBottomOf="parent"
290
-
291
- app:layout_constraintLeft_toLeftOf="parent"
237
+ android:layout_alignParentLeft="true"
292
-
238
+
293
- app:layout_constraintRight_toRightOf="parent"
239
+ android:layout_alignParentTop="true"
294
-
295
- app:layout_constraintTop_toTopOf="parent"/>
240
+
296
-
297
- <Button
298
-
299
- android:onClick="onButton"
241
+ android:onClick="onClick"
300
-
242
+
301
- android:text="開始"
243
+ android:text="録音" />
302
-
303
- android:layout_width="wrap_content"
244
+
304
-
305
- android:layout_height="wrap_content" tools:layout_editor_absoluteY="433dp"
245
+
306
-
307
- tools:layout_editor_absoluteX="174dp"/>
308
246
 
309
247
 
310
248
 
@@ -316,7 +254,11 @@
316
254
 
317
255
  ### 試したこと
318
256
 
257
+ マニフェストには「マイク」と「SDカード」の利用許可を入れております。
258
+
259
+ 上記のソースコードにて、録音しそれをSDカードに保存することはできたのですが
260
+
319
- Handlerを用いて定期的描画を続ければよいの思ったのすが、実装に至っておりません。
261
+ 録音中(録音る音)音量を取得するいうことがておりません。
320
262
 
321
263
  非常に初歩的な質問で申し訳ありませんが
322
264
 

1

プログラミングコードの追加

2019/04/16 04:11

投稿

oto.
oto.

スコア10

test CHANGED
File without changes
test CHANGED
@@ -4,7 +4,13 @@
4
4
 
5
5
  現在、androidstudio(Kotlin)にてAudioRecordで音を録り、音の大きさに応じて
6
6
 
7
- 画面全体の色をリアルタイムに変えるというアプリを作りたいと思っています。
7
+ アプリ画面全体の色をリアルタイムに変えるというアプリを作りたいと思っています。
8
+
9
+
10
+
11
+ 色は五段階程度を想定しております。
12
+
13
+
8
14
 
9
15
 
10
16
 
@@ -26,45 +32,145 @@
26
32
 
27
33
 
28
34
 
29
- ```Kotlin
30
-
31
- import ....
32
-
33
-
34
-
35
- class AudioRecordSample {
36
-
37
-
38
-
39
- private val samplingRate = 44100
40
-
41
- private val frameRate = 10
42
-
43
-
44
-
45
- private val oneFrameDataCount = samplingRate / frameRate
46
-
47
- private val oneFrameSizeInByte = oneFrameDataCount * 2
48
-
49
-
50
-
51
- private val audioBufferSizeInByte =
52
-
53
- max(oneFrameSizeInByte * 10, // 適当に10フレーム分のバッファを持たせた
54
-
55
- android.media.AudioRecord.getMinBufferSize(samplingRate,
56
-
57
- AudioFormat.CHANNEL_IN_MONO,
58
-
59
- AudioFormat.ENCODING_PCM_16BIT))
60
-
61
-
62
-
63
- fun startRecording() {
64
-
65
-
66
-
67
- val audioRecord = AudioRecord(
35
+ デモンストレーションとして「画面表示された『開始』ボタンを押すと、『運勢』という文字が『大吉』に変わる」というプログラムを書きました。
36
+
37
+ そこに AudioRecordクラスを追加し、改造していきたいと思っております。
38
+
39
+
40
+
41
+
42
+
43
+ ```MainActivity
44
+
45
+
46
+
47
+ package com.example.myapplication
48
+
49
+
50
+
51
+ import android.support.v7.app.AppCompatActivity
52
+
53
+ import android.os.Bundle
54
+
55
+ import android.view.View
56
+
57
+ import kotlinx.android.synthetic.main.activity_main.*
58
+
59
+ import android.media.AudioFormat
60
+
61
+ import android.media.AudioRecord
62
+
63
+ import android.media.MediaRecorder
64
+
65
+ import android.util.Log
66
+
67
+ import kotlin.math.max
68
+
69
+
70
+
71
+
72
+
73
+ class MainActivity : AppCompatActivity() {
74
+
75
+
76
+
77
+ override fun onCreate(savedInstanceState: Bundle?) {
78
+
79
+ super.onCreate(savedInstanceState)
80
+
81
+ setContentView(R.layout.activity_main)
82
+
83
+ }
84
+
85
+
86
+
87
+
88
+
89
+ fun onButton(v: View) {
90
+
91
+ tv.text = "大吉"
92
+
93
+ }
94
+
95
+
96
+
97
+
98
+
99
+ /**
100
+
101
+ * AudioRecord クラスのサンプルコード
102
+
103
+ */
104
+
105
+ class AudioRecordSample {
106
+
107
+
108
+
109
+ // サンプリングレート (Hz)
110
+
111
+ // 全デバイスサポート保障は44100のみ
112
+
113
+ private val samplingRate = 44100
114
+
115
+
116
+
117
+ // フレームレート (fps)
118
+
119
+ // 1秒間に何回音声データを処理したいか
120
+
121
+ // 各自好きに決める
122
+
123
+ private val frameRate = 10
124
+
125
+
126
+
127
+ // 1フレームの音声データ(=Short値)の数
128
+
129
+ private val oneFrameDataCount = samplingRate / frameRate
130
+
131
+
132
+
133
+ // 1フレームの音声データのバイト数 (byte)
134
+
135
+ // Byte = 8 bit, Short = 16 bit なので, Shortの倍になる
136
+
137
+ private val oneFrameSizeInByte = oneFrameDataCount * 2
138
+
139
+
140
+
141
+ // 音声データのバッファサイズ (byte)
142
+
143
+ // 要件1:oneFrameSizeInByte より大きくする必要がある
144
+
145
+ // 要件2:デバイスの要求する最小値より大きくする必要がある
146
+
147
+ private val audioBufferSizeInByte =
148
+
149
+ max(
150
+
151
+ oneFrameSizeInByte * 10, // 適当に10フレーム分のバッファを持たせた
152
+
153
+ android.media.AudioRecord.getMinBufferSize(
154
+
155
+ samplingRate,
156
+
157
+ AudioFormat.CHANNEL_IN_MONO,
158
+
159
+ AudioFormat.ENCODING_PCM_16BIT
160
+
161
+ )
162
+
163
+ )
164
+
165
+
166
+
167
+ fun startRecording() {
168
+
169
+
170
+
171
+ // インスタンスの作成
172
+
173
+ val audioRecord = AudioRecord(
68
174
 
69
175
  MediaRecorder.AudioSource.MIC, // 音声のソース
70
176
 
@@ -74,47 +180,73 @@
74
180
 
75
181
  AudioFormat.ENCODING_PCM_16BIT, // PCM16が全デバイスサポート保障
76
182
 
77
- audioBufferSizeInByte) // バッファ
78
-
79
-
80
-
81
- audioRecord.positionNotificationPeriod = oneFrameDataCount
82
-
83
- audioRecord.notificationMarkerPosition = 40000 // 使わないなら設定しない.
84
-
85
-
86
-
87
- val audioDataArray = ShortArray(oneFrameDataCount)
88
-
89
-
90
-
91
- audioRecord.setRecordPositionUpdateListener(object : AudioRecord.OnRecordPositionUpdateListener {
92
-
93
-
94
-
95
- override fun onPeriodicNotification(recorder: AudioRecord) {
96
-
97
- recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
98
-
99
- Log.v("AudioRecord", "onPeriodicNotification size=${audioDataArray.size}")
100
-
101
- }
102
-
103
-
104
-
105
- override fun onMarkerReached(recorder: AudioRecord) {
106
-
107
- recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
108
-
109
- Log.v("AudioRecord", "onMarkerReached size=${audioDataArray.size}")
110
-
111
- }
112
-
113
- })
114
-
115
-
116
-
117
- audioRecord.startRecording()
183
+ audioBufferSizeInByte
184
+
185
+ ) // バッファ
186
+
187
+
188
+
189
+ // 音声データを幾つずつ処理するか( = 1フレームのデータの数)
190
+
191
+ audioRecord.positionNotificationPeriod = oneFrameDataCount
192
+
193
+
194
+
195
+ // ここで指定した数になったタイミングで, 後続の onMarkerReached が呼び出される
196
+
197
+ // 通常のストリーミング処理では必要なさそう?
198
+
199
+ audioRecord.notificationMarkerPosition = 40000 // 使わないなら設定しない.
200
+
201
+
202
+
203
+ // 音声データを格納する配列
204
+
205
+ val audioDataArray = ShortArray(oneFrameDataCount)
206
+
207
+
208
+
209
+ // コールバックを指定
210
+
211
+ audioRecord.setRecordPositionUpdateListener(object : AudioRecord.OnRecordPositionUpdateListener {
212
+
213
+
214
+
215
+ // フレームごとの処理
216
+
217
+ override fun onPeriodicNotification(recorder: AudioRecord) {
218
+
219
+ recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
220
+
221
+ Log.v("AudioRecord", "onPeriodicNotification size=${audioDataArray.size}")
222
+
223
+ // 好きに処理する
224
+
225
+ }
226
+
227
+
228
+
229
+ // マーカータイミングの処理.
230
+
231
+ // notificationMarkerPosition に到達した際に呼ばれる
232
+
233
+ override fun onMarkerReached(recorder: AudioRecord) {
234
+
235
+ recorder.read(audioDataArray, 0, oneFrameDataCount) // 音声データ読込
236
+
237
+ Log.v("AudioRecord", "onMarkerReached size=${audioDataArray.size}")
238
+
239
+ // 好きに処理する
240
+
241
+ }
242
+
243
+ })
244
+
245
+
246
+
247
+ audioRecord.startRecording()
248
+
249
+ }
118
250
 
119
251
  }
120
252
 
@@ -122,6 +254,64 @@
122
254
 
123
255
  ```
124
256
 
257
+ ```activitymain
258
+
259
+ <?xml version="1.0" encoding="utf-8"?>
260
+
261
+ <android.support.constraint.ConstraintLayout
262
+
263
+ xmlns:android="http://schemas.android.com/apk/res/android"
264
+
265
+ xmlns:tools="http://schemas.android.com/tools"
266
+
267
+ xmlns:app="http://schemas.android.com/apk/res-auto"
268
+
269
+ android:layout_width="match_parent"
270
+
271
+ android:layout_height="match_parent"
272
+
273
+ tools:context=".MainActivity">
274
+
275
+
276
+
277
+ <TextView
278
+
279
+ android:id="@+id/tv"
280
+
281
+ android:layout_width="wrap_content"
282
+
283
+ android:layout_height="wrap_content"
284
+
285
+ android:text="今日の運勢"
286
+
287
+ android:textSize="50sp"
288
+
289
+ app:layout_constraintBottom_toBottomOf="parent"
290
+
291
+ app:layout_constraintLeft_toLeftOf="parent"
292
+
293
+ app:layout_constraintRight_toRightOf="parent"
294
+
295
+ app:layout_constraintTop_toTopOf="parent"/>
296
+
297
+ <Button
298
+
299
+ android:onClick="onButton"
300
+
301
+ android:text="開始"
302
+
303
+ android:layout_width="wrap_content"
304
+
305
+ android:layout_height="wrap_content" tools:layout_editor_absoluteY="433dp"
306
+
307
+ tools:layout_editor_absoluteX="174dp"/>
308
+
309
+
310
+
311
+ </android.support.constraint.ConstraintLayout>
312
+
313
+ ```
314
+
125
315
 
126
316
 
127
317
  ### 試したこと