Corona Enterprise - show

Hi guys,

I am looking for one advice.

I am making new game, and I would like to sense user blowing into microphone.
I found out that is only possible if you call some native code (if you are Corona Enterprise).

Now… I am Corona Basic and I finished three games so far…

I am not sure I will be able to produce native code (I am not that experienced).

Can somebody please share simple example, so I could see what Corona Enterprise calling native looks like?

Then I will decide wheather I will go for it or not…

Maybe Corona Enterprise is not for me…

Many thanks.
Ivan

There are some examples in the Enterprise documentation

https://docs.coronalabs.com/native/index.html

I did not find “real examples”.

So If I understand well: I have to write native code in C for iOs and native code in Java for Android?
C cannot cover Android?

Last question: There is no code asset store, like in Unity for example?
Every developer write everything from zero?

Thanks.
Ivan

“Real examples” is a subjective term. There is the “Flashlight” tutorial example that illustrates how to hook into Enterprise.

IOS is in objective C, and Android is in Java. Neither can be applied to the other.

Several developers have posted their Enterprise code in the forum. Also, it’s important to remember that since we’re talking about native code, you can use any of the nearly infinite libs in either Obj-c or Java.

@ivan888,

For simple examples, check out the Corona Enterprise “Quickstart” Tutorials as Alex suggested: https://forums.coronalabs.com/topic/46330-corona-enterprise-quickstart-tutorials/

For real examples, check out Danny Glover’s open sourced Corona Enterprise plugins: https://github.com/GremlinInteractive/

Thanks guys.

Last question: I have to know Objective C and Java to cover both iOs and Android?

I found online code (this is C# I think) that is used to test Microphone inputs.

Can I use this for Android also, or I have to separately  write it in Java?

 

public class MicHandle : MonoBehaviour {
2.
 
3.
  private const int FREQUENCY = 48000;    // Wavelength, I think.
4.
  private const int SAMPLECOUNT = 1024;   // Sample Count.
5.
  private const float REFVALUE = 0.1f;    // RMS value for 0 dB.
6.
  private const float THRESHOLD = 0.02f;  // Minimum amplitude to extract pitch (recieve anything)
7.
  private const float ALPHA = 0.05f;      // The alpha for the low pass filter (I don’t really understand this).
8.
 
9.
  public GameObject resultDisplay;   // GUIText for displaying results
10.
  public GameObject blowDisplay;     // GUIText for displaying blow or not blow.
11.
  public int recordedLength = 50;    // How many previous frames of sound are analyzed.
12.
  public int requiedBlowTime = 4;    // How long a blow must last to be classified as a blow (and not a sigh for instance).
13.
  public int clamp = 160;            // Used to clamp dB (I don’t really understand this either).
14.
 
15.
  private float rmsValue;            // Volume in RMS
16.
  private float dbValue;             // Volume in DB
17.
  private float pitchValue;          // Pitch - Hz (is this frequency?)
18.
  private int blowingTime;           // How long each blow has lasted
19.
 
20.
  private float lowPassResults;      // Low Pass Filter result
21.
  private float peakPowerForChannel; //
22.
 
23.
  private float[] samples;           // Samples
24.
  private float[] spectrum;          // Spectrum
25.
  private List<float> dbValues;      // Used to average recent volume.
26.
  private List<float> pitchValues;   // Used to average recent pitch.
27.
 
28.
  public void Start () {
29.
    samples = new float[SAMPLECOUNT];
30.
    spectrum = new float[SAMPLECOUNT];
31.
    dbValues = new List<float>();
32.
    pitchValues = new List<float>();
33.
 
34.
    StartMicListener();
35.
  }
36.
 
37.
  public void Update () {
38.
 
39.
    // If the audio has stopped playing, this will restart the mic play the clip.
40.
    if (! audio.isPlaying) {
41.
      StartMicListener();
42.
    }
43.
 
44.
    // Gets volume and pitch values
45.
    AnalyzeSound();
46.
 
47.
    // Runs a series of algorithms to decide whether a blow is occuring.
48.
    DeriveBlow();
49.
 
50.
    // Update the meter display.
51.
    if (resultDisplay){
52.
      resultDisplay.guiText.text = “RMS: " + rmsValue.ToString(“F2”) + " (” + dbValue.ToString(“F1”) + " dB)\n" + “Pitch: " + pitchValue.ToString(“F0”) + " Hz”;
53.
    }
54.
  }
55.
 
56.
  /// Starts the Mic, and plays the audio back in (near) real-time.
57.
  private void StartMicListener() {
58.
    audio.clip = Microphone.Start(“Built-in Microphone”, true, 999, FREQUENCY);
59.
    // HACK - Forces the function to wait until the microphone has started, before moving onto the play function.
60.
    while (!(Microphone.GetPosition(“Built-in Microphone”) > 0)) {
61.
    } audio.Play();
62.
  }
63.
 
64.
  /// Credits to aldonaletto for the function, http://goo.gl/VGwKt
65.
  /// Analyzes the sound, to get volume and pitch values.
66.
  private void AnalyzeSound() {
67.
 
68.
    // Get all of our samples from the mic.
69.
    audio.GetOutputData(samples, 0);
70.
 
71.
    // Sums squared samples
72.
    float sum = 0;
73.
    for (int i = 0; i < SAMPLECOUNT; i++){
74.
      sum += Mathf.Pow(samples[i], 2);
75.
    }
76.
 
77.
    // RMS is the square root of the average value of the samples.
78.
    rmsValue = Mathf.Sqrt(sum / SAMPLECOUNT);
79.
    dbValue = 20 * Mathf.Log10(rmsValue / REFVALUE);
80.
 
81.
    // Clamp it to {clamp} min
82.
    if (dbValue < -clamp) {
83.
      dbValue = -clamp;
84.
    }
85.
 
86.
    // Gets the sound spectrum.
87.
    audio.GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);
88.
    float maxV = 0;
89.
    int maxN = 0;
90.
 
91.
    // Find the highest sample.
92.
    for (int i = 0; i < SAMPLECOUNT; i++){
93.
      if (spectrum[i] > maxV  spectrum[i] > THRESHOLD){
94.
        maxV = spectrum[i];
95.
        maxN = i; // maxN is the index of max
96.
      }
97.
    }
98.
 
99.
    // Pass the index to a float variable
100.
    float freqN = maxN;
101.
 
102.
    // Interpolate index using neighbours
103.
    if (maxN > 0  maxN < SAMPLECOUNT - 1) {
104.
      float dL = spectrum[maxN-1] / spectrum[maxN];
105.
      float dR = spectrum[maxN+1] / spectrum[maxN];
106.
      freqN += 0.5f * (dR * dR - dL * dL);
107.
    }
108.
 
109.
    // Convert index to frequency
110.
    pitchValue = freqN * 24000 / SAMPLECOUNT;
111.
  }
112.
 
113.
  private void DeriveBlow() {
114.
 
115.
    UpdateRecords(dbValue, dbValues);
116.
    UpdateRecords(pitchValue, pitchValues);
117.
 
118.
    // Find the average pitch in our records (used to decipher against whistles, clicks, etc).
119.
    float sumPitch = 0;
120.
    foreach (float num in pitchValues) {
121.
      sumPitch += num;
122.
    }
123.
    sumPitch /= pitchValues.Count;
124.
 
125.
    // Run our low pass filter.
126.
    lowPassResults = LowPassFilter(dbValue);
127.
 
128.
    // Decides whether this instance of the result could be a blow or not.
129.
    if (lowPassResults > -30  sumPitch == 0) {
130.
      blowingTime += 1;
131.
    } else {
132.
      blowingTime = 0;
133.
    }
134.
 
135.
    // Once enough successful blows have occured over the previous frames (requiredBlowTime), the blow is triggered.
136.
    // This example says “blowing”, or “not blowing”, and also blows up a sphere.
137.
    if (blowingTime > requiedBlowTime) {
138.
      blowDisplay.guiText.text = “Blowing”;
139.
      GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 1.012f;
140.
    } else {
141.
      blowDisplay.guiText.text = “Not blowing”;
142.
      GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 0.999f;
143.
    }
144.
  }
145.
 
146.
  // Updates a record, by removing the oldest entry and adding the newest value (val).
147.
  private void UpdateRecords(float val, List<float> record) {
148.
    if (record.Count > recordedLength) {
149.
      record.RemoveAt(0);
150.
    }
151.
    record.Add(val);
152.
  }
153.
 
154.
  /// Gives a result (I don’t really understand this yet) based on the peak volume of the record
155.
  /// and the previous low pass results.
156.
  private float LowPassFilter(float peakVolume) {
157.
    return ALPHA * peakVolume + (1.0f - ALPHA) * lowPassResults;
158.
  }
159.
}

The only place Corona can use C# is via Windows phone builds (which you use Visual Studio to build). On iOS you can use a mix of C/C++/Objective-C, on Android you can use C (if you go as deep as the NDK) but most use Java, and you probably should too for this use case.

Most of our plugins (non-ad ones) are also open sourced on our github account:

https://github.com/coronalabs

Thanks guys!

I can build plugins with Corona Enterprise (Small 79$)?

I do not need Unlimited?

Ivan

You can build plugins with a Corona Enterprise Indie license for your personal use in Corona Enterprise projects or for sharing with the community on the Corona plugin store. You can build plugins for other people to use in their Corona Enterprise projects.

If you want to use the Corona SDK Simulator to build projects and not build with Enterprise, you will need Unlimited so you can self-host your plugins.

Rob

Ok, if I got you well: Unlimited can build projects with my plugins  from Corona Simulator and Pro/Small can build projects with my plugins from xCode (not from Simulator).

Thanks.

Ivan

You could build projects from the simulator using your plugins. For other people to use plugins you make, they would have to:

  1. Get it from store.coronalabs.com

  2. Get the plugin files from you and build with Corona Enterprise but not the simulator

  3. Have their own Enterprise Unlimited so they could self-host their own plugins.

Rob

To add-on to what Rob said, with Corona Enterprise Unlimited you can host plugins for your otwn development like so:

  1. Upload the *.tgz file to either a public dropbox folder or your server. More info here: https://docs.coronalabs.com/daily/native/hostedPlugin.html

  2. Add the url to the plugin in your supported platforms table in build.settings (more info in the above link)

  3. Write a plugin stub for mac/win simulators. More info on that here: https://docs.coronalabs.com/native/plugin/submission.html

  4. Build using the corona simulator

Got you! :slight_smile:
Thanks.

I have one last begginer question:

Is generally enough to find some useful code on stack owerflow (Objective C code for iOs platform), and paste it in my plugin with minor modifications to it?

I am talking about simple functions.

Many thanks.
Ivan

There are some examples in the Enterprise documentation

https://docs.coronalabs.com/native/index.html

I did not find “real examples”.

So If I understand well: I have to write native code in C for iOs and native code in Java for Android?
C cannot cover Android?

Last question: There is no code asset store, like in Unity for example?
Every developer write everything from zero?

Thanks.
Ivan

“Real examples” is a subjective term. There is the “Flashlight” tutorial example that illustrates how to hook into Enterprise.

IOS is in objective C, and Android is in Java. Neither can be applied to the other.

Several developers have posted their Enterprise code in the forum. Also, it’s important to remember that since we’re talking about native code, you can use any of the nearly infinite libs in either Obj-c or Java.

@ivan888,

For simple examples, check out the Corona Enterprise “Quickstart” Tutorials as Alex suggested: https://forums.coronalabs.com/topic/46330-corona-enterprise-quickstart-tutorials/

For real examples, check out Danny Glover’s open sourced Corona Enterprise plugins: https://github.com/GremlinInteractive/

Thanks guys.

Last question: I have to know Objective C and Java to cover both iOs and Android?

I found online code (this is C# I think) that is used to test Microphone inputs.

Can I use this for Android also, or I have to separately  write it in Java?

 

public class MicHandle : MonoBehaviour {
2.
 
3.
  private const int FREQUENCY = 48000;    // Wavelength, I think.
4.
  private const int SAMPLECOUNT = 1024;   // Sample Count.
5.
  private const float REFVALUE = 0.1f;    // RMS value for 0 dB.
6.
  private const float THRESHOLD = 0.02f;  // Minimum amplitude to extract pitch (recieve anything)
7.
  private const float ALPHA = 0.05f;      // The alpha for the low pass filter (I don’t really understand this).
8.
 
9.
  public GameObject resultDisplay;   // GUIText for displaying results
10.
  public GameObject blowDisplay;     // GUIText for displaying blow or not blow.
11.
  public int recordedLength = 50;    // How many previous frames of sound are analyzed.
12.
  public int requiedBlowTime = 4;    // How long a blow must last to be classified as a blow (and not a sigh for instance).
13.
  public int clamp = 160;            // Used to clamp dB (I don’t really understand this either).
14.
 
15.
  private float rmsValue;            // Volume in RMS
16.
  private float dbValue;             // Volume in DB
17.
  private float pitchValue;          // Pitch - Hz (is this frequency?)
18.
  private int blowingTime;           // How long each blow has lasted
19.
 
20.
  private float lowPassResults;      // Low Pass Filter result
21.
  private float peakPowerForChannel; //
22.
 
23.
  private float[] samples;           // Samples
24.
  private float[] spectrum;          // Spectrum
25.
  private List<float> dbValues;      // Used to average recent volume.
26.
  private List<float> pitchValues;   // Used to average recent pitch.
27.
 
28.
  public void Start () {
29.
    samples = new float[SAMPLECOUNT];
30.
    spectrum = new float[SAMPLECOUNT];
31.
    dbValues = new List<float>();
32.
    pitchValues = new List<float>();
33.
 
34.
    StartMicListener();
35.
  }
36.
 
37.
  public void Update () {
38.
 
39.
    // If the audio has stopped playing, this will restart the mic play the clip.
40.
    if (! audio.isPlaying) {
41.
      StartMicListener();
42.
    }
43.
 
44.
    // Gets volume and pitch values
45.
    AnalyzeSound();
46.
 
47.
    // Runs a series of algorithms to decide whether a blow is occuring.
48.
    DeriveBlow();
49.
 
50.
    // Update the meter display.
51.
    if (resultDisplay){
52.
      resultDisplay.guiText.text = “RMS: " + rmsValue.ToString(“F2”) + " (” + dbValue.ToString(“F1”) + " dB)\n" + “Pitch: " + pitchValue.ToString(“F0”) + " Hz”;
53.
    }
54.
  }
55.
 
56.
  /// Starts the Mic, and plays the audio back in (near) real-time.
57.
  private void StartMicListener() {
58.
    audio.clip = Microphone.Start(“Built-in Microphone”, true, 999, FREQUENCY);
59.
    // HACK - Forces the function to wait until the microphone has started, before moving onto the play function.
60.
    while (!(Microphone.GetPosition(“Built-in Microphone”) > 0)) {
61.
    } audio.Play();
62.
  }
63.
 
64.
  /// Credits to aldonaletto for the function, http://goo.gl/VGwKt
65.
  /// Analyzes the sound, to get volume and pitch values.
66.
  private void AnalyzeSound() {
67.
 
68.
    // Get all of our samples from the mic.
69.
    audio.GetOutputData(samples, 0);
70.
 
71.
    // Sums squared samples
72.
    float sum = 0;
73.
    for (int i = 0; i < SAMPLECOUNT; i++){
74.
      sum += Mathf.Pow(samples[i], 2);
75.
    }
76.
 
77.
    // RMS is the square root of the average value of the samples.
78.
    rmsValue = Mathf.Sqrt(sum / SAMPLECOUNT);
79.
    dbValue = 20 * Mathf.Log10(rmsValue / REFVALUE);
80.
 
81.
    // Clamp it to {clamp} min
82.
    if (dbValue < -clamp) {
83.
      dbValue = -clamp;
84.
    }
85.
 
86.
    // Gets the sound spectrum.
87.
    audio.GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);
88.
    float maxV = 0;
89.
    int maxN = 0;
90.
 
91.
    // Find the highest sample.
92.
    for (int i = 0; i < SAMPLECOUNT; i++){
93.
      if (spectrum[i] > maxV  spectrum[i] > THRESHOLD){
94.
        maxV = spectrum[i];
95.
        maxN = i; // maxN is the index of max
96.
      }
97.
    }
98.
 
99.
    // Pass the index to a float variable
100.
    float freqN = maxN;
101.
 
102.
    // Interpolate index using neighbours
103.
    if (maxN > 0  maxN < SAMPLECOUNT - 1) {
104.
      float dL = spectrum[maxN-1] / spectrum[maxN];
105.
      float dR = spectrum[maxN+1] / spectrum[maxN];
106.
      freqN += 0.5f * (dR * dR - dL * dL);
107.
    }
108.
 
109.
    // Convert index to frequency
110.
    pitchValue = freqN * 24000 / SAMPLECOUNT;
111.
  }
112.
 
113.
  private void DeriveBlow() {
114.
 
115.
    UpdateRecords(dbValue, dbValues);
116.
    UpdateRecords(pitchValue, pitchValues);
117.
 
118.
    // Find the average pitch in our records (used to decipher against whistles, clicks, etc).
119.
    float sumPitch = 0;
120.
    foreach (float num in pitchValues) {
121.
      sumPitch += num;
122.
    }
123.
    sumPitch /= pitchValues.Count;
124.
 
125.
    // Run our low pass filter.
126.
    lowPassResults = LowPassFilter(dbValue);
127.
 
128.
    // Decides whether this instance of the result could be a blow or not.
129.
    if (lowPassResults > -30  sumPitch == 0) {
130.
      blowingTime += 1;
131.
    } else {
132.
      blowingTime = 0;
133.
    }
134.
 
135.
    // Once enough successful blows have occured over the previous frames (requiredBlowTime), the blow is triggered.
136.
    // This example says “blowing”, or “not blowing”, and also blows up a sphere.
137.
    if (blowingTime > requiedBlowTime) {
138.
      blowDisplay.guiText.text = “Blowing”;
139.
      GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 1.012f;
140.
    } else {
141.
      blowDisplay.guiText.text = “Not blowing”;
142.
      GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 0.999f;
143.
    }
144.
  }
145.
 
146.
  // Updates a record, by removing the oldest entry and adding the newest value (val).
147.
  private void UpdateRecords(float val, List<float> record) {
148.
    if (record.Count > recordedLength) {
149.
      record.RemoveAt(0);
150.
    }
151.
    record.Add(val);
152.
  }
153.
 
154.
  /// Gives a result (I don’t really understand this yet) based on the peak volume of the record
155.
  /// and the previous low pass results.
156.
  private float LowPassFilter(float peakVolume) {
157.
    return ALPHA * peakVolume + (1.0f - ALPHA) * lowPassResults;
158.
  }
159.
}

The only place Corona can use C# is via Windows phone builds (which you use Visual Studio to build). On iOS you can use a mix of C/C++/Objective-C, on Android you can use C (if you go as deep as the NDK) but most use Java, and you probably should too for this use case.