View Full Version : Speed up audio accurately
rhlee
19th April 2012, 18:01
Hi,
I have a PAL TV. When I play 24p videos, I first change the frame rate and then speed up the audio by (25*1001)/(24*1000)~=1.04.... . The only way I can speed up audio accurately is using an avisynth script. Other tools end up being out of sync after 30mins to 1hr.
Are there any open source tools on linux that can accurately speed up audio to this degree of prescision?
I was thinking of writing my own tool, but I was wanted to know if there was one out there first.
Richard
tebasuna51
19th April 2012, 22:33
Then you play 23.976 fps videos (there are also 24 exact fps)
If audio is AC3 you can use this command line:
eac3to input.ac3 output.ac3 -23.976 -changeTo25.000
There are also GUI's for eac3to (HDStreamExtractor, UsEac3to, ...)
rhlee
20th April 2012, 01:36
Thanks for the recomendation, but I don't think it runs under linux.
tebasuna51
20th April 2012, 10:19
Sorry I don't see your requirement, after see AviSynth script ...
BTW, eac3to and UsEac3to seems work fine under wine.
sneaker_ger
20th April 2012, 15:26
Try SoX, or Hybrid (http://www.selur.de) if you want a GUI.
rhlee
23rd April 2012, 11:07
Again thanks for the recommendations, but I decicded to write my own as I needed someting that was:
1. Accurate, because if the speed up factor is off by 0.00001 you will end up with desync towards the end of the movie.
2. Command line based, for ease of automation.
The code is below. It's extremely rough, but I got perfect synchronisation. (https://github.com/rhlee/speed-alpha if anyones interested.)
One problem I had was that after using the ratio of 1001 / 960 (24p -> PAL). I still got desync at the end. But I realised that probably 24p is not played at exactly 24000/1001 fps. I.e. the frame rate is not stored as a rational number, but as a decimal. ffmpeg reported the frame rate as 23.98 and vlc as 23.976023 . In the end I just went to the end of the movie, and calculated the desync/position and multiplied by that. Does anyone know how I can obtain the exact framerate from the mp4 container/stream?
Also once I ended up with a synced wav file. I re-encoded it to aac then muxed with video into mp4. By the time I played on my PVR (which uses it own movie player) is was a constant 0.5s out. I'm relatively new to encoding, but I take it audio delays on PVRs / proprietary players is a common problem?
I'm not sure how relavent frame rate conversion is nowadays with HDTV. But if people are interested, I could write something usable for release.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <sys/time.h>
FILE *inputFile, *outputFile;
long inputLowerSample;
long double lastInterrupt;
void sigInt(int signal);
void finally();
int main(int argc, char *argv[])
{
double factor = 1001.0 / 960.0;
factor *= (1 + (0.5 / (90.0 * 60.0)));
inputFile = fopen("sample.wav", "r");
outputFile = fopen("test.wav", "w");
if(setvbuf(inputFile, NULL, _IOFBF, 4096) ||
setvbuf(outputFile, NULL, _IOFBF, 4096))
{
perror("Could not set file buffer\n");
exit(1);
}
if(sizeof(short) != 2)
{
perror("Short is not 2 bytes\n");
exit(1);
}
signal(SIGINT, sigInt);
long inputSample = -1, outputSample = 0;
double inputTime;
short lowerInputChannel[2], upperInputChannel[2], outputChannel[2];
for(outputSample = 0; 1; outputSample++)
{
inputTime = factor * (outputSample + 0.5);
inputLowerSample = floor(inputTime - 0.5);
while(inputSample < (inputLowerSample + 1))
{
lowerInputChannel[0] = upperInputChannel[0];
lowerInputChannel[1] = upperInputChannel[1];
if(fread(upperInputChannel, 2, 2, inputFile) != 2) finally();
inputSample++;
}
outputChannel[0] = ((upperInputChannel[0] - lowerInputChannel[0]) *
(inputTime - inputLowerSample - 0.5)) + lowerInputChannel[0];
outputChannel[1] = ((upperInputChannel[1] - lowerInputChannel[1]) *
(inputTime - inputLowerSample - 0.5)) + lowerInputChannel[1];
fwrite(outputChannel, 2, 2, outputFile);
}
finally();
}
void sigInt(int signal)
{
struct timeval time;
gettimeofday(&time, NULL);
long double interrupt = time.tv_sec + (time.tv_usec / 1000000.0);
if((interrupt - lastInterrupt) < 1.0) finally();
lastInterrupt = interrupt;
fprintf(stderr, "\nProcessed %.1fM (Press CTRL+C twice to exit)\n",
inputLowerSample / 262144.0);
}
void finally()
{
fclose(inputFile);
fclose(outputFile);
exit(0);
}
sneaker_ger
23rd April 2012, 14:04
But I realised that probably 24p is not played at exactly 24000/1001 fps. I.e. the frame rate is not stored as a rational number, but as a decimal. ffmpeg reported the frame rate as 23.98 and vlc as 23.976023 . In the end I just went to the end of the movie, and calculated the desync/position and multiplied by that. Does anyone know how I can obtain the exact framerate from the mp4 container/stream?
I think that mp4 actually allows exact 24000/1001, because it uses some kind of timebase system.
SoX is command-line based, btw. (And I never heard anyone complain about its precision.)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.