I have an iOS app that reads text using the OpenEars API. I am using the latest version (1.2.5). I can not figure out how to change the pitch while the words are being read ("on the fly"). I created a slider to control the pitch. A delegate is fired as the slider is changed. In the delegate function, the FliteController target_mean is changed. The intent was to have the pitch change as soon as the target_mean value was changed. My code is as follows:
-(void)sayTheMessage:(NSString *)message {
// if there is nothing there, don't try to say anything
if (message == nil)
return;
[self.oeeo setDelegate:self];
// we are going to say what is in the label...
#try {
// set the pitch, etc...
self.flite.target_mean = pitchValue; // Change the pitch
self.flite.target_stddev = varienceValue; // Change the variance
self.flite.duration_stretch = speedValue; // Change the speed
// finally say it!
[self.flite say:message withVoice:self.slt];
}
#catch (NSException *exception) {
if ([delegate respondsToSelector:#selector(messageError)])
[delegate messageError];
}
#finally {
}
}
-(void)changePitch:(float)pitch {
if ((pitch >= 0) && (pitch <= 2)) {
// save the new pitch internally
pitchValue = pitch;
// change the pitch of the current speaking....
self.flite.target_mean = pitchValue;
}
}
Any ideas?
OpenEars developer here. You can't change the pitch on the fly with FliteController since the pitch is set before speech is processed.
Related
I am creating video in ARKit during session. When I press record button, camera freezes. I have written code in didUpdateFrame delegate that causes the problem. There I save scene.snapshot in an array. Also when i create video from these images, app crashes with following message in debugger:
Message from debugger: Terminated due to memory issue
-(void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame
{
if (_recordButton.state == UIControlStateSelected)
{
currentState = Recording;
[self saveImage];
}
else if (previousState == Recording)
{
NSLog(#"Stop recording");
currentState = NotRecording;
recordTime = NULL;
self.nextButton.enabled=YES;
}
//update recording state per frame update
previousState = currentState;
}
-(void)saveImage
{
UIImage *image = self.sceneView.snapshot;
[self.bufferArray addObject:image];
image = nil;
}
Do not use ARSCNView.snapshot with implementing ARSessionDelegate.didUpdateFrame. I had same issue and solution was do not implement ARSessionDelegate.didUpdateFrame. I have used CADisplayLink with ARSCNView.snapshot and it works well.
I also tried to use ARFrame.capturedImage, but it has not contain AR objects at all. ARSCNView.snapshot contains them.
I have two scenes - DifficultScene and GameScene. In DifficultScene I have three buttons - easy, medium and hard. I use a global variable Bool to keep track of the current difficulty level. When I try easy mode everything works fine, but when I try medium or hard, bool is changing every second, jumping from hard to medium and easy, making game unplayable. My question is - how can I fix it? Here are code were it happens:
GamesScene.m
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
extern BOOL isEasyMode;
extern BOOL isMediumMode;
extern BOOL isHardMode;
if ((isEasyMode = YES)) {
NSLog(#"easy");
[self computer];
}
if ((isMediumMode = YES)) {
NSLog(#"medium");
[self computerMedium];
}
if ((isHardMode = YES)) {
NSLog(#"hard");
[self computerHard];
}
[self scoreCount];
}
(if more code is needed, i will post it)
I think your update method calls periodically as per timer so it will get called continuously if it so then. Thats why it is happening i think and another major thing is you should use == for comparison. you are using (isEasyMode = YES) that means you are assigning YES to isEasyMode.
So replce all if statement like if ((isEasyMode = YES)) with if (isEasyMode == YES).
Update :
if statement should like,
if (isEasyMode == YES) {
NSLog(#"easy");
[self computer];
}
Hope this will help :)
I have an application which requires to use the microphone for recording user voice. I'm trying to make a speech to text.
I'm work with SpeechKit.framework and below is my code used:
-(void)starRecording{
self.voiceSearch = [[SKRecognizer alloc] initWithType:SKSearchRecognizerType
detection:SKShortEndOfSpeechDetection
language:[[USER_DEFAULT valueForKey:LANGUAGE_SPEECH_DIC] valueForKey:#"record"]
delegate:self];
}
- (void)recognizer:(SKRecognizer *)recognizer didFinishWithResults:(SKRecognition *)results {
long numOfResults = [results.results count];
if (numOfResults > 0) {
// update the text of text field with best result from SpeechKit
self.recordString = [results firstResult];
[self sendChatWithMediaType:#"messageCall" MediaUrl:#"" ContactDetail:#"{}" LocationDetail:#"{}"];
[self.voiceSearch stopRecording];
}
if (self.voiceSearch) {
[self.voiceSearch cancel];
}
[self starRecording];
}
That makes the SKRecognizer to be always open and that thing reduce the application performance.
I want to start the SKRecognizer when the microphone is detecting input audio.
I have a method for that? A method which is called when the microphone have input sound for me or a method which is always returning the level of audio detected?
Thank you!
You need to use the SpeechKit class to set up the audio.
Look here for details;
http://www.raywenderlich.com/60870/building-ios-app-like-siri
This project shows how to detect audio threshold;
github.com/picciano/iOS-Audio-Recoginzer
I've a strange behavior with CMMotionManager. I try to calibrate the position of my device to enable my App to support multiple device orientations.
When I debug my App on a real device (not in Simulator), everything is working fine.
When I run the same App without debugging, the calibration does not work.
Here's my code:
static CMMotionManager* _motionManager;
static CMAttitude* _referenceAttitude;
// Returns a vector with the current orientation values
// At the first call a reference orientation is saved to ensure the motion detection works for multiple device positions
+(GLKVector3)getMotionVectorWithLowPass{
// Motion
CMAttitude *attitude = self.getMotionManager.deviceMotion.attitude;
if (_referenceAttitude==nil) {
// Cache Start Orientation
_referenceAttitude = [_motionManager.deviceMotion.attitude copy];
} else {
// Use start orientation to calibrate
[attitude multiplyByInverseOfAttitude:_referenceAttitude];
NSLog(#"roll: %f", attitude.roll);
}
return [self lowPassWithVector: GLKVector3Make(attitude.pitch,attitude.roll,attitude.yaw)];
}
+(CMMotionManager*)getMotionManager {
if (_motionManager==nil) {
_motionManager=[[CMMotionManager alloc]init];
_motionManager.deviceMotionUpdateInterval=0.25;
[_motionManager startDeviceMotionUpdates];
}
return _motionManager;
}
I've found a solution. The issue was caused due the different timing behavior between debug and non debug mode. CMMotionManager needs a little time for initializing, before it returns correct values. The solution was to postpone the calibration for 0.25 seconds.
This code works:
+(GLKVector3)getMotionVectorWithLowPass{
// Motion
CMAttitude *attitude = self.getMotionManager.deviceMotion.attitude;
if (_referenceAttitude==nil) {
// Cache Start Orientation
// NEW:
[self performSelector:#selector(calibrate) withObject:nil afterDelay:0.25];
} else {
// Use start orientation to calibrate
[attitude multiplyByInverseOfAttitude:_referenceAttitude];
NSLog(#"roll: %f", attitude.roll);
}
return [self lowPassWithVector: GLKVector3Make(attitude.pitch,attitude.roll,attitude.yaw)];
}
// NEW:
+(void)calibrate
_referenceAttitude = [self.getMotionManager.deviceMotion.attitude copy]
}
I'm writing a game where a MainGameplay class keeps track of whose turn it is by setting an ivar to an enum value:
typedef enum {
GAME_NOT_STARTED,
PLAYER_1_TO_MOVE,
PLAYER_2_TO_MOVE
} WhoseTurnIsIt;
Then the GameBoard class checks whether a move attempt is valid, and calls either turnEnded:(WhoseTurnIsIt)turn or reportTurnFailure:(WhoseTurnIsIt)turn in MainGameplay.m.
I get EXC_BAD_ACCESS as soon as I try to access this returned value back in MainGameplay, in the receiving methods. Seems like I should retain something, but you can't retain an enum. In the debugger the values are there, so I don't understand what's being accessed improperly.
This is the code doing the calling in GameBoard:
-(void)buttonPressed:(id)sender {
CCArray *kids = [[[CCDirector sharedDirector] runningScene] children];
if (!mainScene) { // mainScene is an ivar on each the GameBoard's buttons.
for (CCScene *s in kids) {
// this looks crazy because the "main" scene is actually a controlling layer that has as a child the main gameplay layer:
if ([s isKindOfClass:[ControlLayer class]]) {
self->mainScene = (MainGameplay *)((ControlLayer *) s).gameLayer;
}
}
}
if (MOVE_NO_ERROR == [self checkMove:mainScene.turn]) {
[self setMove:mainScene.turn];
[mainScene turnEnded:mainScene.turn]; // This line and the next are the ones causing the EXC_BAD_ACCESS
} else [mainScene reportTurnFailure:mainScene.turn]; // This line too.
}
EDIT Functions in mainScene being called go like this:
-(void) reportTurnFailure:(WhoseTurnIsIt)_turn {
NSLog(#"MainScene still valid"); // This line works fine
NSLog(#"Bzzzzzt. Player %#, try again", _turn); // This line crashes BUT _turn shows up with a proper value in the debugger.
}
_turn is not an object, but the %# format specifier says that the argument is an object. Use %i instead.
-(void) reportTurnFailure:(WhoseTurnIsIt)_turn {
NSLog(#"MainScene still valid"); // This line works fine
NSLog(#"Bzzzzzt. Player %i, try again", _turn); // This line crashes BUT _turn shows up with a proper value in the debugger.
}