RICOH Blog Post: "Making Sounds with a RICOH THETA V"

Let’s Cheer for Team Japan using a THETA! THETA Plug-in Development #thetaplugin

This is Ricoh’s @kushimoto.

RICOH THETA V uses an Android-based OS, so functionality can be expanded by installing apps. In the world of THETA, apps are called plug-ins. If you are interested in developing plug-ins, please see these links:

In this article, I’ll introduce how to make sounds with a THETA. Let’s use it to cheer for the Team Japan at the World Cup!

Making Sounds with a THETA

API

There is an API offered which plays back audio used in THETA.

It’s amazingly cool for THETA fans - the shutter sound of “queeeeen” and the force quit sound of “pipipipipi” can be played whenever you want.

Using the API, the following intents are defined, and audio can be played by broadcasting the intents.

Controlling Speakers | THETA Plug-in API Reference Broadcast Intent

INTENT DESCRIPTION
“com.theta360.plugin.ACTION_AUDIO_SHUTTER” Shutter Audio
“com.theta360.plugin.ACTION_AUDIO_SH_OPEN” Long Exposure Shutter Audio Start
“com.theta360.plugin.ACTION_AUDIO_SH_CLOSE” Long Exposure Shutter Audio End
“com.theta360.plugin.ACTION_AUDIO_MOVSTART” Video Recording Start Audio
“com.theta360.plugin.ACTION_AUDIO_MOVSTOP” Video Recording Stop Audio
“com.theta360.plugin.ACTION_AUDIO_SELF” Self Timer Audio
“com.theta360.plugin.ACTION_AUDIO_WARNING” Warning Audio!

SDK

The SDK is provided in order to help plug-in development.

RICOH THETA Plug-in SDK

Besides audio, functions such as get button operation event and LED control are included. Please refer to the links below for the use of SDK.

Methods to support the above audio related API are defined in the PluginActivity class in the SDK.

  • notificationAudioShutter()
  • notificationAudioOpen()
  • notificationAudioClose()
  • notificationAudioMovStart()
  • notificationAudioMovStop()
  • notificationAudioSelf()
  • notificationAudioWarning()

Sound is made when method is called.

Cheering Team Japan with THETA

OK, let’s get to the main part.

It was so sad that Team Japan didn’t go further in the World Cup. This article didn’t make it out before the game, but I’m sure there are always another team representing Japan in some fashion. So, I’m going to introduce you to the way to cheer for those representing Japan by using THETA.

Beat Vuvuzela!

So, when you think of a traditional Japanese cheer…

In Japan, the cheer of all cheers is called san-san-nana-byoshi meaning the 3-3-7 Cheer. Everyone knows it, and there is no licensing issue. The perfect cheer.

So, let’s develop a THETA that can play the 3-3-7 Cheer!

Beat Vuvuzela!

CODING

MainActivity.java included in SDK’s sample code is modified.

For detailed explanation of sample code, please see @meronpan’s article.

package com.theta360.pluginapplication;

import android.os.Bundle;
import android.view.KeyEvent;
import com.theta360.pluginapplication.task.TakePictureTask;
import com.theta360.pluginapplication.task.TakePictureTask.Callback;
import com.theta360.pluginlibrary.activity.PluginActivity;
import com.theta360.pluginlibrary.callback.KeyCallback;
import com.theta360.pluginlibrary.receiver.KeyReceiver;
import com.theta360.pluginlibrary.values.LedColor;
import com.theta360.pluginlibrary.values.LedTarget;

public class MainActivity extends PluginActivity {
    private static final int INTERVAL = 350;

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

        // Set a callback when a button operation event is acquired.
        setKeyCallback(new KeyCallback() {
            // Makes the sound pi
            private void pi() throws InterruptedException {
                notificationLedShow(LedTarget.LED3);
                notificationAudioMovStart();
                Thread.sleep(INTERVAL);
                notificationLedHide(LedTarget.LED3);
            }

            // Makes the longer sound pii
            private void pii() throws InterruptedException {
                notificationLedShow(LedTarget.LED4);
                notificationAudioShutter();
                Thread.sleep(INTERVAL);
                notificationLedHide(LedTarget.LED4);
            }

            @Override
            public void onKeyDown(int keyCode, KeyEvent event) {
                if (keyCode == KeyReceiver.KEYCODE_CAMERA) {

                    try {
                        // play pi 3 times
                        pi();
                        pi();
                        pi();

                        // rest
                        Thread.sleep(INTERVAL);

                        // play pi 3 times
                        pi();
                        pi();
                        pi();

                        // rest
                        Thread.sleep(INTERVAL);

                        // play pi 7 times
                        pi();
                        pi();
                        pi();
                        pi();
                        pi();
                        pi();
                        pii();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onKeyUp(int keyCode, KeyEvent event) {
            }

            @Override
            public void onKeyLongPress(int keyCode, KeyEvent event) {
            }
        });
    }
}

Explaining it simply…

    @Override
    public void onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
            try {
                // play pi 3 times
                pi();
                pi();
                pi();

                // rest
                Thread.sleep(INTERVAL);

                // play pi 3 times
                pi();
                pi();
                pi();

                // rest
                Thread.sleep(INTERVAL);

                // play pi 7 times
                pi();
                pi();
                pi();
                pi();
                pi();
                pi();
                pii();

                // rest
                Thread.sleep(INTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

When the button is pressed, onKeyDown() is called, and in this case when the shutter button (KEYCODE_CAMERA) is pressed, it’ll do the 3-3-7 Cheer.

Normally you’d go for implementing Thread.sleep() during the main thread, but here we’re prioritizing the readability of the sample code.

    // Play the pi sound
    private void pi() throws InterruptedException {
        notificationLedShow(LedTarget.LED3);
        notificationAudioMovStart();
        Thread.sleep(INTERVAL);
        notificationLedHide(LedTarget.LED3);
    }

    // Play the longer pii sound
    private void pii() throws InterruptedException {
        notificationLedShow(LedTarget.LED4);
        notificationAudioShutter();
        Thread.sleep(INTERVAL);
        notificationLedHide(LedTarget.LED4);
    }

This is the actual method for making the THETA make sounds. However, it’s not that cool to just have the audio, so let’s light the LEDs. How to light the LEDs is explained also in the article written by @meronpan.

The 3-3-7 Cheer with THETA

Here is how it looks when running.

Mind blowing!

Conclusion

In this article, how to play THETA audio was introduced, and a THETA which played the 3-3-7 Cheer was programmed.

If this article had come out before the World Cup…we could have cheered with THETA… perhaps.

If you are interested in THETA plug-in development, please register for the partner program!

Please be aware that the THETA with its serial number registered with the program will no longer be eligible for standard end-user support.

For detailed information regarding partner program please see here.

The registration form is here.