Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

Commit

Permalink
Added voice trigger ("show me a demo"); updated code style to match t…
Browse files Browse the repository at this point in the history
…hat of other samples.
  • Loading branch information
allevato committed Dec 17, 2013
1 parent 450fb7f commit c74f94c
Show file tree
Hide file tree
Showing 11 changed files with 394 additions and 346 deletions.
29 changes: 23 additions & 6 deletions AndroidManifest.xml
@@ -1,6 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.glass.samples.waveform"
package="com.google.android.glass.sample.waveform"
android:versionCode="1"
android:versionName="1.0" >

Expand All @@ -12,15 +27,17 @@

<application
android:allowBackup="true"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
android:label="@string/app_name" >

<activity
android:name="com.google.glass.samples.waveform.WaveformActivity"
android:label="@string/app_name" >
android:name="com.google.android.glass.sample.waveform.WaveformActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data android:name="com.google.android.glass.VoiceTrigger"
android:resource="@xml/trigger_show_me_a_demo" />
</activity>

</application>

</manifest>
54 changes: 14 additions & 40 deletions README.md
@@ -1,48 +1,22 @@
apk-waveform-sample
=====================
Waveform
========

A simple Glassware apk that receives audio input from the microphone and
displays it on the screen as an animated waveform, along with the decibel
This sample launches an immersion that receives audio input from the microphone
and displays it on the screen as an animated waveform, along with the decibel
level.

## Prerequistes
## Getting started

* [Android SDK](http://developer.android.com/sdk/index.html) - This is needed for development.
* [Glass](http://www.google.com/glass/start/how-to-get-one/) - You can push the code to an Android device but the goal of this project is to get started writing .apk for Glass.
Check out our documentation to learn how to get started on
https://developers.google.com/glass/develop/index

## Importing and compiling the code
## Running the sample on Glass

Checkout the code into your filesystem and use your favorite IDE to import and compile the code.
You can use your IDE to compile and install the sample or use
[`adb`](https://developer.android.com/tools/help/adb.html)
on the command line:

### In Eclipse and ADT
$ adb install -r WaveformSample.apk

1. Click **File > Import ... > Existing Android Code into Workspace**.
2. Click **Browse**, select the location of the `apk-waveform-sample/` directory, and click **OK**.
3. Select the **apk-waveform-sample** project to import it and select
**Copy projects into workspace**.
6. Click **Finish** to complete the import.

### In Android Studio

1. Checkout the sample to a location where you keep your Android
development projects. A `apk-waveform-sample/` directory is created.
2. Click **File > Import Project...**, select the location of the `apk-waveform-sample/` directory, and click **Next** until you see the **Finish** button.
3. Click **Finish** to complete the import.


## Turning on debug mode

You'll need to turn on debug mode before you do any type of development on
Glass. Go to **Settings > Device Info > Turn on debug** to enable it.

## Push the .apk on Glass

You can use your IDE to compile, push and run the .apk or use this command line with `adb`:

adb install -r apk-waveform-sample.apk

## Run the .apk

You can use your IDE to run the .apk or use this command line with `adb` when the Glass screen is **on**:

adb shell am start -n com.google.glass.samples.waveform/.WaveformActivity
To start the sample, say "ok glass, show me a demo" from the Glass clock
screen or use the touch menu.
31 changes: 22 additions & 9 deletions res/layout/layout_waveform.xml
@@ -1,23 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:background="@color/black"
tools:context=".WaveformActivity" >
android:layout_height="match_parent" >

<com.google.glass.samples.waveform.WaveformView
android:id="@+id/waveformView"
<com.google.android.glass.sample.waveform.WaveformView
android:id="@+id/waveform_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<TextView
android:id="@+id/decibelView"
android:id="@+id/decibel_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginRight="@dimen/footer_right_margin"
android:layout_marginBottom="@dimen/footer_bottom_margin"
android:textSize="@dimen/footer_text_size" />
android:textAppearance="?android:attr/textAppearanceSmall" />

</FrameLayout>
4 changes: 0 additions & 4 deletions res/values/colors.xml

This file was deleted.

18 changes: 17 additions & 1 deletion res/values/dimens.xml
@@ -1,6 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<resources>

<dimen name="footer_right_margin">40px</dimen>
<dimen name="footer_bottom_margin">29px</dimen>
<dimen name="footer_text_size">30px</dimen>

</resources>
19 changes: 19 additions & 0 deletions res/values/strings.xml
@@ -1,5 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<resources>

<string name="app_name">Waveform</string>
<string name="show_me_a_demo">show me a demo</string>

<string name="decibel_format">%1$.1f dB</string>

</resources>
17 changes: 17 additions & 0 deletions res/xml/trigger_show_me_a_demo.xml
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<trigger keyword="@string/show_me_a_demo" />
145 changes: 145 additions & 0 deletions src/com/google/android/glass/sample/waveform/WaveformActivity.java
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.android.glass.sample.waveform;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;
import android.widget.TextView;

/**
* Receives audio input from the microphone and displays a visualization of that data as a waveform
* on the screen.
*/
public class WaveformActivity extends Activity {

// The sampling rate for the audio recorder.
private static final int SAMPLING_RATE = 44100;

private WaveformView mWaveformView;
private TextView mDecibelView;

private RecordingThread mRecordingThread;
private int mBufferSize;
private short[] mAudioBuffer;
private String mDecibelFormat;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_waveform);

mWaveformView = (WaveformView) findViewById(R.id.waveform_view);
mDecibelView = (TextView) findViewById(R.id.decibel_view);

// Compute the minimum required audio buffer size and allocate the buffer.
mBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
mAudioBuffer = new short[mBufferSize / 2];

mDecibelFormat = getResources().getString(R.string.decibel_format);
}

@Override
protected void onResume() {
super.onResume();

mRecordingThread = new RecordingThread();
mRecordingThread.start();
}

@Override
protected void onPause() {
super.onPause();

if (mRecordingThread != null) {
mRecordingThread.stopRunning();
mRecordingThread = null;
}
}

/**
* A background thread that receives audio from the microphone and sends it to the waveform
* visualizing view.
*/
private class RecordingThread extends Thread {

private boolean mShouldContinue = true;

@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);

AudioRecord record = new AudioRecord(AudioSource.MIC, SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mBufferSize);
record.startRecording();

while (shouldContinue()) {
record.read(mAudioBuffer, 0, mBufferSize / 2);
mWaveformView.updateAudioData(mAudioBuffer);
updateDecibelLevel();
}

record.stop();
record.release();
}

/**
* Gets a value indicating whether the thread should continue running.
*
* @return true if the thread should continue running or false if it should stop
*/
private synchronized boolean shouldContinue() {
return mShouldContinue;
}

/** Notifies the thread that it should stop running at the next opportunity. */
public synchronized void stopRunning() {
mShouldContinue = false;
}

/**
* Computes the decibel level of the current sound buffer and updates the appropriate text
* view.
*/
private void updateDecibelLevel() {
// Compute the root-mean-squared of the sound buffer and then apply the formula for
// computing the decibel level, 20 * log_10(rms). This is an uncalibrated calculation
// that assumes no noise in the samples; with 16-bit recording, it can range from
// -90 dB to 0 dB.
double sum = 0;

for (short rawSample : mAudioBuffer) {
double sample = rawSample / 32768.0;
sum += sample * sample;
}

double rms = Math.sqrt(sum / mAudioBuffer.length);
final double db = 20 * Math.log10(rms);

// Update the text view on the main thread.
mDecibelView.post(new Runnable() {
@Override
public void run() {
mDecibelView.setText(String.format(mDecibelFormat, db));
}
});
}
}
}

0 comments on commit c74f94c

Please sign in to comment.