Speeding up flite TTS in iOS - iphone

I understand that it may be possible to speed up flite TTS in iOS by removing unused voices. How is this done?
I have some text that seems to take about 45 seconds to convert (on iPhone 3G) but I only have 30 seconds. I am starting the conversion as soon as possible and preloading the AV player already but I am still a little too slow.

This trick will not really speed up flite but will free up the device to do other things while flite is doing it's thing:
Add this method:
- (void)speak:(NSString *)message {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[fliteEngine speakText:message];
[pool release];
}
When you want ti to speak, call it with this:
[self performSelectorInBackground:#selector(speak:) withObject:#"Text to speak!"];
This will put your app into multi-treaded mode and will render the speech and play it as a background thread. This will allow your app to go off and do other things while this is happening. I have also noticed that it seems to render the text a little faster this way. Hopefully it will give you the little bit you need.

Removing voices makes no difference in the speed. One voice, "cmu_us_kal" is much faster than the others. I did not perform speed tests on all of the others but kal is at least 5 times faster than "cmu_us_rms" which I had been using.

You can convert in shorter sentences or phrases. Then start playing one converted speech segment while still converting the rest in a background thread.

Related

iPhone/iOS: Best practices to shorten launch time of an app?

I found it took 4-5 seconds on an iPhone4/iOS6.0 device, and I want to know what is the system doing in that time, are there any best practices to short the launch time of an app?
many thanks.
EDIT:
I log it and it took about 1.5s in applicationDidFinishLaunchingWithoptions:
,and it is like 3.5-4s(I used a clock to get a preciser time) from I tap the app icon to its launch screen disappear.That is to say, about 2-2.5s to launch the app before calling applicationDidFinishLaunchingWithoptions
Simply watch Session 225 Up and Running: Making a Great Impression with Every Launch from WWDC 2012, it will take you through the process of profiling your app launch and give tips on most often made mistakes, it's great.
There is a very very good WWDC 2012 video with a long sequence devoted to exactly this topic: Session 235 (Responsiveness). I strongly recommend that you watch it. It gives you lots of hints and tricks for speeding up launch (don't link to too many libraries, etc.), tells you how to measure and how to read your measurements in Instruments, etc.
The system isn't what's causing your app to take 4-5 seconds to launch. It's probably your code in applicationDidFinishLaunching, or the init, viewDidLoad, or other setup methods of your root view controller.
Profile your app on a real device with the 'Time Profiler' Instrument. Only launch your app, don't press any buttons on the UI once it's launched. We only want to see what's going on during launch.
I would suggest checking the 'Separate by Thread,' 'Invert Call Tree,' 'Hide System Libraries,' and 'Show Obj-C Only' options under 'Call Tree' on the lower left side of the window.
Once you've checked your chosen options, go down the list of method calls. Start with the ones taking the most time (for obvious reasons). You can double click on symbol names to get more detailed information on where time was spent. Good luck!
We had the same problem.
Ultimately, we sped up launch time significantly by preloading the video in viewDidAppear. By the time the user taps the play button to launch the movie, enough content has loaded so that it can begin playback almost immediately.
e.g.:
- (void)viewDidAppear:(BOOL)animated {
NSURL *movieURL = [NSURL URLWithString:#"http://static.example.com/movie.mov"];
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
vc.moviePlayer.shouldAutoplay = NO;
[vc.moviePlayer prepareToPlay];
self.moviePlayerViewController = vc;
}
Full details in this blog post: http://blog.tetherpad.com/blog/2013/3/22/improving-tutorial-movie-load-times-on-ios-for-fun-and-profit
In my opinion, the launch time mainly cost in function,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
If you do a bunch of stuff which blocks process, it will take long for launch.
So you can optimise your applicationDidFinishLaunching by moving out some unnecessary code which you can do later. Or you can make your code non-block, for example, you should use asynchronous network requests in applicationDidFinishLaunching instead of synchronous ones.

Cocos Denshion: Play sound effect in sync with music

I am making a music game and when the user presses a note it will produce a sound. The sound naturally needs to play immediately when the user presses, so they can tell whether they are in time with the music. However, it feels as if the sound is lagging, especially when note presses become quicker.
My background .m4a music file is played with AVAudioPlayer. I chose to use this over Cocos Denshion as I have access to the currentTime property. I may be wrong, but I dont think I can access this with CocosDenshion.
I made a .wav file which is extremely short (less than a second). I preload my sound effect on init:
[[SimpleAudioEngine sharedEngine] preloadEffect:#"Assist.wav"];
Then to play the sound effect, in CCTouchesBegan I call:
[[SimpleAudioEngine sharedEngine] playEffect:#"Assist.wav"];
After that it calls my code to determine the users timing and awards points. Any idea why it might be lagging, or a better way to play sound effects in time with music?
EDIT: Ive tried a few things recently with no results. First I tried playing the sounds automatically as they came up to the appropriate time in the song. Still had the lag, so I dont think it is touch events being slow. I also tried 3 different sound libraries.
However, when I ran in the simulator, it seemed to not be laggy. Does anyone have an idea? Im clueless and its a major feature I cant really take out...
you should avoid this code:- [[SimpleAudioEngine sharedEngine] preloadEffect:#"Assist.wav"];
with the start of app you should load your framework SimpleAudioEngine by writing this code :-
//SimpleAudioEngine *palySound; made object in .h file.
palySound=[SimpleAudioEngine sharedEngine];
and whenever you want to play sound you can write: [palySound playEffect:#"Assist.wav"];
I am not sure what you're doing in your SoundEngine, but in my own experience, the best way to not get lag to play a sound is to assign an AVAudioPlayer for each sound file (unless you want to start messing around with AudioQueues).
Here it is an example:
Let's assume that you have an AVAudioPlayer *assistPlayer; in your current view controller.
In your viewDidLoad initialize it with your sound:
NSURL *wavURL = [[NSBundle mainBundle] URLForResource:#"Assist" withExtension:#"wav"];
assistPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:wavURL error:nil];
Then, in your IBAction where you want to play the file, just do:
[assistPlayer play];
You shouldn't get any lag.
Did you try Finch? It claims to play sounds with low latency, and it is also just a wrapper around OpenAL.
Other than that, I'm really not experienced with OpenAL, but can think of two possible reasons for your lag:
The main thread is too busy - Try to offload work from it to other
threads.
Perhaps OpenAL is defined with too large of a buffer, so the pipeline loads the entire sound into the buffer (or a big chunk of it), and only afterwards the playback starts.

How to play sound at precise moments on iPhone?

I'm working on creating a simple metronome on the iPhone. What the app does right now is to run a timer, entering the timer's function every 1/1000th of second. Then it checks the current time vs time of starting the app (I'm using CACurrentMediaTime() function).
CFTimeInterval currentTime = CACurrentMediaTime();
if (self.beatingStartTime == 0) {
self.beatingStartTime = currentTime;
}
if ( (currentTime - self.beatingStartTime) >= self.timeIntevalBetweenTicks * self.internalTimerCounter ) {
self.internalTimerCounter ++;
// ...
}
If there is a good moment to play audio, the code using OpenAL to play it gets fired.
Basicly that's it. I checked the sounds played when running both in simulator as well as on 2 devices (iPad and jailbroken iPhone 3GS) and there is a problem - when I recorded the sound and reviewed the waveform in Reaper software, some sounds play a bit too late, and some of them - bit too early (even I could understand the "too late" part, I don't really get how it can play earlier then it should - since the app checks the number of seconds every time, it basicly can't be ealier then specified time - yet it is, according to my recods).
At the same time there are some metronome apps that are known for being "rock-solid" when it comes to timing, so I guess there is a way. I just wonder what I'm missing...
edit: Changing timer call from 1/1000th second to, for example 1/100th doesn't help.
edit 2: When I switched from timer to threads (and I put the thread to sleep for specified time) I still get a strange behavior. The tempo moves around and while I could understand a little lag and playing some sounds too late, the problem is some of them do play too early - it means time distance between 2 beats is less then the time that should pass.
The diffrence is about 3%, which translates to about 10-15 miliseconds, which is quite a lot for me. Anyone got an idea why the sound can play earlier? I tried it both on iPhone simulator and on iPad actual device, and my only guess is there's something wrong with the timer - CACurrentMediaTime() returning more seconds that it should. Is it even possible?
Try using an NSSound, and load it up as an instance variable and don't release it unless your metronome isn't running. Delays can be caused by loading the file into memory on the loop. The other thing to consider is that a metronome probably doesn't need to poll every 1/1000th of a second. If you do it less often, you're less likely to saturate the CPU and you might get more consistent results.
Lastly, check out how Apple's demo works: http://developer.apple.com/library/ios/#samplecode/Metronome/Introduction/Intro.html
Might give you a better idea how to accomplish what you're trying to do :)
What you want is COCOS DENSHION which is a simple reliable easy to use sound library, that we have found solves all problems.
I (just personally) don't like "Cocos2D" but you can just take and use CocosDenshion.
Secondly -- 1000th of a second is ridiculous for a timer. Just totally forget it.
Thirdly -- AVAudioPlayer is worthless as you found.
Note - "ObjectAL" is a new, perhaps better, alternative
to CocosDenshion. Check it out.

AudioServices (Easy), AVAudioPlayer (Medium), OpenAL (Hard & Overkill?)

I need to play sounds (~5 seconds each) throughout my iphone application. When they're triggered, they need to play immediately.
For the moment I'm using AudioServices and (as you probably know) the first time you play a sound it lags, then every time there after it's perfect. Is there some code available that's clever enough to preload an AudioServices sound (by playing it silently maybe?). I've read adjusting the system volume programmatically will get your app rejected, so that's not an option. Seems AudioServices isn't made for volume correction from what I can see.
I've looked into OpenAL and while feasible seems a little over kill. AVAudioPlayer seems like a little bit of a better option, I'm using that for background music at present. Extending my music player to handle a 'sound board' might be my last resort.
On the topic of OpenAL, does anyone know of a place with a decent (app store friendly) OpenAL wrapper for the iPhone?
Thanks in advance
Finch could be perfect for you. It’s a tiny wrapper around OpenAL with very low latency and simple API. See also all SO questions tagged ‘Finch’.
If you use an AVAudioPlayer, you can call prepareToPlay when you initialize the object to reduce the delay between calling play and having the audio start.

What do you use to play sound in iPhone games?

I have a performance-intensive iPhone game I would like to add sounds to. There seem to be about three main choices: (1) AVAudioPlayer, (2) Audio Queues and (3) OpenAL. I’d hate to write pages of low-level code just to play a sample, so that I would like to use AVAudioPlayer. The problem is that it seems to kill the performace – I’ve done a simple measuring using CFAbsoluteTimeGetCurrent and the play message seems to take somewhere from 9 to 30 ms to finish. That’s quite miserable, considering that 25 ms == 40 fps.
Of course there is the prepareToPlay method that should speed things up. That’s why I wrote a simple class that keeps several AVAudioPlayers at its disposal, prepares them beforehand and then plays the sample using the prepared player. No cigar, still it takes the ~20 ms I mentioned above.
Such performance is unusable for games, so what do you use to play sounds with a decent performance on iPhone? Am I doing something wrong with the AVAudioPlayer? Do you play sounds with Audio Queues? (I’ve written something akin to AVAudioPlayer before 2.2 came out and I would love to spare that experience.) Do you use OpenAL? If yes, is there a simple way to play sounds with OpenAL, or do you have to write pages of code?
Update: Yes, playing sounds with OpenAL is fairly simple.
AVAudioPlayer is very marginal for game audio. Tackling AudioQueue or OpenAL by adapting one of the examples is definitely the way to go. latency is much more controllable that way.
If you're calling play on the main thread, try running it on a separate thread. What I ended up doing is:
#include <dispatch/dispatch.h>
dispatch_queue_t playQueue = dispatch_queue_create("com.example.playqueue", NULL);
AVAudioPlayer* player = ...
dispatch_async(playQueue, ^{
[player play];
});
which fixed the worst of the framerate stuttering I was experiencing.
I use OpenAL and the classes that came with the CrashLanding sample code. It's worked fine so far to play samples and play looped music all at the same time. I'm currently learning how to release the memory I've allocated for a sound (.wav file) when, for example, I want to play some intro music just once.
Use CocosDenshion – it’s free, easy, and works. It wraps AVAudioPlayer for background tracks and OpenAL for sounds.
Do you want to check the buffering with the implementation you're using? It might be somehow related to the 20ms delay you're experiencing. i.e., try to play around with the buffer size.