You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ma...@apache.org on 2016/03/28 00:38:18 UTC
cordova-plugin-media git commit: CB-9487: Support getting amplitude
for recording
Repository: cordova-plugin-media
Updated Branches:
refs/heads/master e5b663ac9 -> 3706b7576
CB-9487: Support getting amplitude for recording
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/commit/3706b757
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/tree/3706b757
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/diff/3706b757
Branch: refs/heads/master
Commit: 3706b757679d1470cb7a02a09c92e6faf52687b9
Parents: e5b663a
Author: Simon MacDonald <si...@gmail.com>
Authored: Sun Mar 27 17:54:20 2016 -0400
Committer: Simon MacDonald <si...@gmail.com>
Committed: Sun Mar 27 18:36:05 2016 -0400
----------------------------------------------------------------------
README.md | 43 ++++++++++++++++++++++++++
src/android/AudioHandler.java | 17 +++++++++-
src/android/AudioPlayer.java | 25 +++++++++++++--
src/ios/CDVSound.h | 3 +-
src/ios/CDVSound.m | 63 ++++++++++++++++++++++++++++++--------
tests/tests.js | 31 +++++++++++--------
www/Media.js | 10 +++++-
7 files changed, 162 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index a641e39..6ea4956 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,8 @@ The following constants are reported as the only parameter to the
### Methods
+- `media.getCurrentAmplitude`: Returns the current position within an audio file.
+
- `media.getCurrentPosition`: Returns the current position within an audio file.
- `media.getDuration`: Returns the duration of an audio file.
@@ -120,6 +122,47 @@ The following constants are reported as the only parameter to the
- __duration__: The duration of the media, in seconds.
+## media.getCurrentAmplitude
+
+Returns the current amplitude of the current recording.
+
+ media.getCurrentAmplitude(mediaSuccess, [mediaError]);
+
+### Supported Platforms
+
+- Android
+- iOS
+
+### Parameters
+
+- __mediaSuccess__: The callback that is passed the current amplitude (0.0 - 1.0).
+
+- __mediaError__: (Optional) The callback to execute if an error occurs.
+
+### Quick Example
+
+ // Audio player
+ //
+ var my_media = new Media(src, onSuccess, onError);
+
+ // Record audio
+ my_media.startRecord();
+
+ mediaTimer = setInterval(function () {
+ // get media amplitude
+ my_media.getCurrentAmplitude(
+ // success callback
+ function (amp) {
+ console.log(amp + "%");
+ },
+ // error callback
+ function (e) {
+ console.log("Error getting amp=" + e);
+ }
+ );
+ }, 1000);
+
+
## media.getCurrentPosition
Returns the current position within an audio file. Also updates the `Media` object's `position` parameter.
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/src/android/AudioHandler.java
----------------------------------------------------------------------
diff --git a/src/android/AudioHandler.java b/src/android/AudioHandler.java
index 2ff601d..75cdcde 100644
--- a/src/android/AudioHandler.java
+++ b/src/android/AudioHandler.java
@@ -164,6 +164,10 @@ public class AudioHandler extends CordovaPlugin {
else if (action.equals("messageChannel")) {
messageChannel = callbackContext;
return true;
+ } else if (action.equals("getCurrentAmplitudeAudio")) {
+ float f = this.getCurrentAmplitudeAudio(args.getString(0));
+ callbackContext.sendPluginResult(new PluginResult(status, f));
+ return true;
}
else { // Unrecognized action.
return false;
@@ -471,5 +475,16 @@ public class AudioHandler extends CordovaPlugin {
}
-
+ /**
+ * Get current amplitude of recording.
+ * @param id The id of the audio player
+ * @return amplitude
+ */
+ public float getCurrentAmplitudeAudio(String id) {
+ AudioPlayer audio = this.players.get(id);
+ if (audio != null) {
+ return (audio.getCurrentAmplitude());
+ }
+ return 0;
+ }
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/src/android/AudioPlayer.java
----------------------------------------------------------------------
diff --git a/src/android/AudioPlayer.java b/src/android/AudioPlayer.java
index ede9330..26248e5 100644
--- a/src/android/AudioPlayer.java
+++ b/src/android/AudioPlayer.java
@@ -501,13 +501,13 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
sendErrorStatus(MEDIA_ERR_ABORTED);
}
return false;//we´re not ready yet
- }
+ }
else {
//reset the audio file
player.seekTo(0);
player.pause();
- return true;
- }
+ return true;
+ }
} else {
//reset the player
this.player.reset();
@@ -598,4 +598,23 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.handler.sendEventMessage("status", statusDetails);
}
+
+ /**
+ * Get current amplitude of recording.
+ *
+ * @return amplitude or 0 if not recording
+ */
+ public float getCurrentAmplitude() {
+ if (this.recorder != null) {
+ try{
+ if (this.state == STATE.MEDIA_RUNNING) {
+ return (float) this.recorder.getMaxAmplitude() / 32762;
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return 0;
+ }
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/src/ios/CDVSound.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVSound.h b/src/ios/CDVSound.h
index 90da62e..5e795cc 100644
--- a/src/ios/CDVSound.h
+++ b/src/ios/CDVSound.h
@@ -110,8 +110,9 @@ typedef NSUInteger CDVMediaMsg;
- (void)startRecordingAudio:(CDVInvokedUrlCommand*)command;
- (void)stopRecordingAudio:(CDVInvokedUrlCommand*)command;
+- (void)getCurrentAmplitudeAudio:(CDVInvokedUrlCommand*)command;
- (void)setVolume:(CDVInvokedUrlCommand*)command;
- (void)setRate:(CDVInvokedUrlCommand*)command;
-@end
\ No newline at end of file
+@end
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/src/ios/CDVSound.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVSound.m b/src/ios/CDVSound.m
index 640ebcd..d99f181 100644
--- a/src/ios/CDVSound.m
+++ b/src/ios/CDVSound.m
@@ -206,7 +206,7 @@
[errorDict setObject:[NSNumber numberWithUnsignedInteger:code] forKey:@"code"];
[errorDict setObject:message ? message:@"" forKey:@"message"];
-
+
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:errorDict options:0 error:nil];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
@@ -290,7 +290,7 @@
float customRate = [rate floatValue];
[avPlayer setRate:customRate];
}
-
+
[[self soundCache] setObject:audioFile forKey:mediaId];
}
}
@@ -420,7 +420,7 @@
if ([resourceURL isFileURL]) {
audioFile.player = [[CDVAudioPlayer alloc] initWithContentsOfURL:resourceURL error:&playerError];
} else {
- /*
+ /*
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:resourceURL];
NSString* userAgent = [self.commandDelegate userAgent];
if (userAgent) {
@@ -541,10 +541,10 @@
} else if (avPlayer != nil) {
int32_t timeScale = avPlayer.currentItem.asset.duration.timescale;
CMTime timeToSeek = CMTimeMakeWithSeconds(posInSeconds, timeScale);
-
+
BOOL isPlaying = (avPlayer.rate > 0 && !avPlayer.error);
BOOL isReadyToSeek = (avPlayer.status == AVPlayerStatusReadyToPlay) && (avPlayer.currentItem.status == AVPlayerItemStatusReadyToPlay);
-
+
// CB-10535:
// When dealing with remote files, we can get into a situation where we start playing before AVPlayer has had the time to buffer the file to be played.
// To avoid the app crashing in such a situation, we only seek if both the player and the player item are ready to play. If not ready, we send an error back to JS land.
@@ -613,7 +613,7 @@
}
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:position];
-
+
NSString* jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);", @"cordova.require('cordova-plugin-media.Media').onStatus", mediaId, MEDIA_POSITION, position];
[self.commandDelegate evalJs:jsString];
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
@@ -636,7 +636,7 @@
void (^startRecording)(void) = ^{
NSError* __autoreleasing error = nil;
-
+
if (audioFile.recorder != nil) {
[audioFile.recorder stop];
audioFile.recorder = nil;
@@ -656,14 +656,20 @@
return;
}
}
-
+
// create a new recorder for each start record
+ NSDictionary *audioSettings = @{AVFormatIDKey: @(kAudioFormatMPEG4AAC),
+ AVSampleRateKey: @(44100),
+ AVNumberOfChannelsKey: @(1),
+ AVEncoderAudioQualityKey: @(AVAudioQualityMedium)
+ };
audioFile.recorder = [[CDVAudioRecorder alloc] initWithURL:audioFile.resourceURL settings:nil error:&error];
-
+
bool recordingSuccess = NO;
if (error == nil) {
audioFile.recorder.delegate = weakSelf;
audioFile.recorder.mediaId = mediaId;
+ audioFile.recorder.meteringEnabled = YES;
recordingSuccess = [audioFile.recorder record];
if (recordingSuccess) {
NSLog(@"Started recording audio sample '%@'", audioFile.resourcePath);
@@ -671,7 +677,7 @@
[weakSelf.commandDelegate evalJs:jsString];
}
}
-
+
if ((error != nil) || (recordingSuccess == NO)) {
if (error != nil) {
errorMsg = [NSString stringWithFormat:@"Failed to initialize AVAudioRecorder: %@\n", [error localizedFailureReason]];
@@ -686,7 +692,7 @@
[weakSelf.commandDelegate evalJs:jsString];
}
};
-
+
SEL rrpSel = NSSelectorFromString(@"requestRecordPermission:");
if ([self hasAudioSession] && [self.avSession respondsToSelector:rrpSel])
{
@@ -710,7 +716,7 @@
} else {
startRecording();
}
-
+
} else {
// file did not validate
NSString* errorMsg = [NSString stringWithFormat:@"Could not record audio at '%@'", audioFile.resourcePath];
@@ -831,6 +837,39 @@
[[self soundCache] removeAllObjects];
}
+- (void)getCurrentAmplitudeAudio:(CDVInvokedUrlCommand*)command
+{
+ NSString* callbackId = command.callbackId;
+ NSString* mediaId = [command argumentAtIndex:0];
+
+#pragma unused(mediaId)
+ CDVAudioFile* audioFile = [[self soundCache] objectForKey:mediaId];
+ float amplitude = 0; // The linear 0.0 .. 1.0 value
+
+ if ((audioFile != nil) && (audioFile.recorder != nil) && [audioFile.recorder isRecording]) {
+ [audioFile.recorder updateMeters];
+ float minDecibels = -60.0f; // Or use -60dB, which I measured in a silent room.
+ float decibels = [audioFile.recorder averagePowerForChannel:0];
+ if (decibels < minDecibels) {
+ amplitude = 0.0f;
+ } else if (decibels >= 0.0f) {
+ amplitude = 1.0f;
+ } else {
+ float root = 2.0f;
+ float minAmp = powf(10.0f, 0.05f * minDecibels);
+ float inverseAmpRange = 1.0f / (1.0f - minAmp);
+ float amp = powf(10.0f, 0.05f * decibels);
+ float adjAmp = (amp - minAmp) * inverseAmpRange;
+ amplitude = powf(adjAmp, 1.0f / root);
+ }
+ }
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:amplitude];
+
+ NSString* jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%.3f);", @"cordova.require('cordova-plugin-media.Media').onStatus", mediaId, MEDIA_POSITION, amplitude];
+ [self.commandDelegate evalJs:jsString];
+ [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+ }
+
@end
@implementation CDVAudioFile
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/tests/tests.js
----------------------------------------------------------------------
diff --git a/tests/tests.js b/tests/tests.js
index 246e40b..08c0ff7 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -25,7 +25,7 @@
// increased timeout for actual playback to give device chance to download and play mp3 file
// some emulators can be REALLY slow at this, so two minutes
var ACTUAL_PLAYBACK_TEST_TIMEOUT = 2 * 60 * 1000;
-
+
var isWindows = cordova.platformId == 'windows8' || cordova.platformId == 'windows';
// detect whether audio hardware is available and enabled
var isAudioSupported = isWindows ? Windows.Media.Devices.MediaDevice.getDefaultAudioRenderId(Windows.Media.Devices.AudioDeviceRole.default) : true;
@@ -168,7 +168,14 @@ exports.defineAutoTests = function () {
media1.release();
});
- it("media.spec.15 should return MediaError for bad filename", function (done) {
+ it("media.spec.15 should contain a getCurrentAmplitude function", function () {
+ var media1 = new Media("dummy");
+ expect(media1.getCurrentAmplitude).toBeDefined();
+ expect(typeof media1.getCurrentAmplitude).toBe('function');
+ media1.release();
+ });
+
+ it("media.spec.16 should return MediaError for bad filename", function (done) {
//bb10 dialog pops up, preventing tests from running
if (cordova.platformId === 'blackberry10') {
pending();
@@ -203,7 +210,7 @@ exports.defineAutoTests = function () {
}
});
- it("media.spec.16 position should be set properly", function (done) {
+ it("media.spec.17 position should be set properly", function (done) {
// no audio hardware available
if (!isAudioSupported) {
pending();
@@ -233,7 +240,7 @@ exports.defineAutoTests = function () {
media.play();
}, ACTUAL_PLAYBACK_TEST_TIMEOUT);
- it("media.spec.17 duration should be set properly", function (done) {
+ it("media.spec.18 duration should be set properly", function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10') {
pending();
}
@@ -262,7 +269,7 @@ exports.defineAutoTests = function () {
media.play();
}, ACTUAL_PLAYBACK_TEST_TIMEOUT);
- it("media.spec.20 should be able to resume playback after pause", function (done) {
+ it("media.spec.19 should be able to resume playback after pause", function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10') {
pending();
}
@@ -297,15 +304,15 @@ exports.defineAutoTests = function () {
}
};
media = new Media(mediaFile, successCallback, failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context), statusChange);
-
+
// CB-10535: Play after a few secs, to give allow enough buffering of media file before seeking
setTimeout(function() {
media.play();
}, 4000);
-
+
}, ACTUAL_PLAYBACK_TEST_TIMEOUT);
- it("media.spec.21 should be able to seek through file", function (done) {
+ it("media.spec.20 should be able to seek through file", function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10') {
pending();
}
@@ -330,23 +337,23 @@ exports.defineAutoTests = function () {
}
};
media = new Media(mediaFile, successCallback, failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context), statusChange);
-
+
// CB-10535: Play after a few secs, to give allow enough buffering of media file before seeking
setTimeout(function() {
media.play();
}, 4000);
-
+
}, ACTUAL_PLAYBACK_TEST_TIMEOUT);
});
- it("media.spec.18 should contain a setRate function", function () {
+ it("media.spec.21 should contain a setRate function", function () {
var media1 = new Media("dummy");
expect(media1.setRate).toBeDefined();
expect(typeof media1.setRate).toBe('function');
media1.release();
});
- it("media.spec.19 playback rate should be set properly using setRate", function (done) {
+ it("media.spec.22 playback rate should be set properly using setRate", function (done) {
if (cordova.platformId !== 'ios') {
expect(true).toFailWithMessage('Platform does not supported this feature');
pending();
http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/3706b757/www/Media.js
----------------------------------------------------------------------
diff --git a/www/Media.js b/www/Media.js
index d302cbe..192d4b3 100644
--- a/www/Media.js
+++ b/www/Media.js
@@ -163,6 +163,14 @@ Media.prototype.setRate = function(rate) {
}
};
+/**
+ * Get amplitude of audio.
+ */
+Media.prototype.getCurrentAmplitude = function(success, fail) {
+ exec(function(p) {
+ success(p);
+ }, fail, "Media", "getCurrentAmplitudeAudio", [this.id]);
+};
/**
* Audio has status update.
@@ -232,4 +240,4 @@ if (cordova.platformId === 'android' || cordova.platformId === 'amazon-fireos' |
exec(onMessageFromNative, undefined, 'Media', 'messageChannel', []);
channel.initializationComplete('onMediaPluginReady');
});
-}
\ No newline at end of file
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org