달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
728x90
반응형

안드로이드 - 기기의 마이크로 들어오는 소리의 데시벨을 구하는 방법
원본 출처:"http://susemi99.tistory.com/1017
주요 소스는 여기를 참고했다.
http://code.google.com/p/moonblink/


 

HomeActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    
public class HomeActivity extends Activity
{
    private AudioReader audioReader;
    private int sampleRate = 8000;
    private int inputBlockSize = 256;
    private int sampleDecimate = 1;
      
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
          
        audioReader = new AudioReader();
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
    }
      
    public void doStart(View v)
    {
        audioReader.startReader(sampleRate, inputBlockSize * sampleDecimate, new AudioReader.Listener()
        {
            @Override
            public final void onReadComplete(int dB)
            {
                receiveDecibel(dB);
            }
              
            @Override
            public void onReadError(int error)
            {
                  
            }
        });
    }
      
    private void receiveDecibel(final int dB)
    {
        Log.e("###", dB+" dB");
    }
      
    public void doStop(View v)
    {
        audioReader.stopReader();
    }
}


데시벨을 표시한다.

AudioReader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
public class AudioReader
{
    public static abstract class Listener
    {
        public static final int ERR_OK = 0;
        public static final int ERR_INIT_FAILED = 1;
        public static final int ERR_READ_FAILED = 2;
        public abstract void onReadComplete(int decibel);
        public abstract void onReadError(int error);
    }
      
    public int calculatePowerDb(short[] sdata, int off, int samples)
    {
        double sum = 0;
        double sqsum = 0;
        for (int i = 0; i < samples; i++)
        {
            final long v = sdata[off + i];
            sum += v;
            sqsum += v * v;
        }
        double power = (sqsum - sum * sum / samples) / samples;
          
        power /= MAX_16_BIT * MAX_16_BIT;
          
        double result = Math.log10(power) * 10f + FUDGE;
        return (int)result;
    }
      
    public AudioReader()
    {
    }
      
    public void startReader(int rate, int block, Listener listener)
    {
        Log.i(TAG, "Reader: Start Thread");
        synchronized (this)
        {
            int audioBuf = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT) * 2;
              
            audioInput = new AudioRecord(MediaRecorder.AudioSource.MIC, rate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, audioBuf);
            inputBlockSize = block;
            sleepTime = (long) (1000f / ((float) rate / (float) block));
            inputBuffer = new short[2][inputBlockSize];
            inputBufferWhich = 0;
            inputBufferIndex = 0;
            inputListener = listener;
            running = true;
            readerThread = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    readerRun();
                }
            }, "Audio Reader");
            readerThread.start();
        }
    }
      
    public void stopReader()
    {
        Log.i(TAG, "Reader: Signal Stop");
        synchronized (this)
        {
            running = false;
        }
        try
        {
            if (readerThread != null)
                readerThread.join();
        } catch (InterruptedException e)
        {
            ;
        }
        readerThread = null;
          
        // Kill the audio input.
        synchronized (this)
        {
            if (audioInput != null)
            {
                audioInput.release();
                audioInput = null;
            }
        }
          
        Log.i(TAG, "Reader: Thread Stopped");
    }
      
    private void readerRun()
    {
        short[] buffer;
        int index, readSize;
          
        int timeout = 200;
        try
        {
            while (timeout > 0 && audioInput.getState() != AudioRecord.STATE_INITIALIZED)
            {
                Thread.sleep(50);
                timeout -= 50;
            }
        } catch (InterruptedException e)
        {
        }
          
        if (audioInput.getState() != AudioRecord.STATE_INITIALIZED)
        {
            Log.e(TAG, "Audio reader failed to initialize");
            readError(Listener.ERR_INIT_FAILED);
            running = false;
            return;
        }
          
        try
        {
            Log.i(TAG, "Reader: Start Recording");
            audioInput.startRecording();
            while (running)
            {
                long stime = System.currentTimeMillis();
                  
                if (!running)
                    break;
                  
                readSize = inputBlockSize;
                int space = inputBlockSize - inputBufferIndex;
                if (readSize > space)
                    readSize = space;
                buffer = inputBuffer[inputBufferWhich];
                index = inputBufferIndex;
                  
                synchronized (buffer)
                {
                    int nread = audioInput.read(buffer, index, readSize);
                      
                    boolean done = false;
                    if (!running)
                        break;
                      
                    if (nread < 0)
                    {
                        Log.e(TAG, "Audio read failed: error " + nread);
                        readError(Listener.ERR_READ_FAILED);
                        running = false;
                        break;
                    }
                    int end = inputBufferIndex + nread;
                    if (end >= inputBlockSize)
                    {
                        inputBufferWhich = (inputBufferWhich + 1) % 2;
                        inputBufferIndex = 0;
                        done = true;
                    }
                    else
                        inputBufferIndex = end;
                      
                    if (done)
                    {
                        readDone(buffer);
                          
                        long etime = System.currentTimeMillis();
                        long sleep = sleepTime - (etime - stime);
                        if (sleep < 5)
                            sleep = 5;
                        try
                        {
                            buffer.wait(sleep);
                        } catch (InterruptedException e)
                        {
                        }
                    }
                }
            }
        } finally
        {
            Log.i(TAG, "Reader: Stop Recording");
            if (audioInput.getState() == AudioRecord.RECORDSTATE_RECORDING)
                audioInput.stop();
        }
    }
      
    private void readDone(short[] buffer)
    {
        synchronized (this)
        {
            audioData = buffer;
            ++audioSequence;
              
            short[] buffer2 = null;
            if (audioData != null && audioSequence > audioProcessed)
            {
                audioProcessed = audioSequence;
                buffer2 = audioData;
            }
              
            if (buffer2 != null)
            {
                final int len = buffer2.length;
                inputListener.onReadComplete(calculatePowerDb(buffer2, 0, len));
                buffer2.notify();
            }
        }
    }
      
    private void readError(int code)
    {
        inputListener.onReadError(code);
    }
      
    private static final String TAG = "WindMeter";
    private AudioRecord audioInput;
    private short[][] inputBuffer = null;
    private int inputBufferWhich = 0;
    private int inputBufferIndex = 0;
    private int inputBlockSize = 0;
    private long sleepTime = 0;
    private Listener inputListener = null;
    private boolean running = false;
    private Thread readerThread = null;
    private short[] audioData;
    private long audioSequence = 0;
    private long audioProcessed = 0;
    private static final float MAX_16_BIT = 32768;
    private static final float FUDGE = 0.6f;
}


가져 온 소스에다 몇개 추가를 했다. 주석까지 있는 버전은 아래 파일을 받으시길...
근데 문제는 0dB가 최대치이고, 보통은 -40dB정도 나온다.
중간에 계산식을 바꾸면 될 것 같은데, 아 몰라 뭐야 무서워

728x90
반응형
:
Posted by mapagilove