
radford+myth at blackbean
Nov 15, 2002, 4:52 AM
Post #1 of 8
(1869 views)
Permalink
|
|
[PATCH] mono support, take two
|
|
Hi John, On Mon, Nov 18, 2002 at 11:53:03PM -0500, John Coiner wrote: > It would be great to parameterize all of the player/recorder code in > terms of 'channels' and 'bytes_per_sample' etc. The option to use mono > would be pretty sweet for people with mono tuners, especially if they > don't have the world's fastest CPU. Ok here it is. I actually have sound now for the first time. And it's in sync! > ( By the way -- if you're going to work on the player -- take a minute > to see if you can figure out how the audio buffer's read pointer could > "lap" the write pointer. This should never happen, though Isaac seems to > have observed just this. We were stymied, the code looked pretty solid, > to me anyway...) Will do, now that I have a better grasp on the code. -Jim Index: libs/libNuppelVideo/NuppelVideoPlayer.cpp =================================================================== RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoPlayer.cpp,v retrieving revision 1.96 diff -u -r1.96 NuppelVideoPlayer.cpp --- libs/libNuppelVideo/NuppelVideoPlayer.cpp 18 Nov 2002 01:59:38 -0000 1.96 +++ libs/libNuppelVideo/NuppelVideoPlayer.cpp 19 Nov 2002 10:37:59 -0000 @@ -41,6 +41,7 @@ #define wsEnter 0x8d + 256 #define wsReturn 0x0d + 256 +int audio_ioctl_int(int fd, int arg, int *value, const char *decscription); NuppelVideoPlayer::NuppelVideoPlayer(void) { @@ -75,7 +76,9 @@ weMadeBuffer = false; osd = NULL; + audio_channels = 2; audio_samplerate = 44100; + audio_bits_per_sample = 16; editmode = false; advancevideo = resetvideo = advancedecoder = false; @@ -171,13 +174,13 @@ void NuppelVideoPlayer::InitSound(void) { - int bits = 16, stereo = 1, speed = audio_samplerate, caps; + int caps; if (usingextradata) { - bits = extradata.audio_bits_per_sample; - stereo = (extradata.audio_channels == 2); - speed = extradata.audio_sample_rate; + audio_bits_per_sample = extradata.audio_bits_per_sample; + audio_channels = extradata.audio_channels; + audio_samplerate = extradata.audio_sample_rate; } if (disableaudio) @@ -194,25 +197,10 @@ return; } - if (ioctl(audiofd, SNDCTL_DSP_SAMPLESIZE, &bits) < 0) - { - cerr << "problem setting sample size, exiting\n"; - close(audiofd); - audiofd = -1; - return; - } - - if (ioctl(audiofd, SNDCTL_DSP_STEREO, &stereo) < 0) - { - cerr << "problem setting to stereo, exiting\n"; - close(audiofd); - audiofd = -1; - return; - } - - if (ioctl(audiofd, SNDCTL_DSP_SPEED, &speed) < 0) + if(audio_ioctl_int(audiofd, SNDCTL_DSP_CHANNELS, &audio_channels, "audio output channels") < 0 || + audio_ioctl_int(audiofd, SNDCTL_DSP_SPEED, &audio_samplerate, "audio output samplerate") < 0 || + audio_ioctl_int(audiofd, SNDCTL_DSP_SAMPLESIZE, &audio_bits_per_sample, "audio output bits per sample") < 0) { - cerr << "problem setting sample rate, exiting\n"; close(audiofd); audiofd = -1; return; @@ -480,7 +468,11 @@ foundit = 0; effdsp = audio_samplerate; if (usingextradata) + { effdsp = extradata.audio_sample_rate; + audio_channels = extradata.audio_channels; + audio_bits_per_sample = extradata.audio_bits_per_sample; + } while (!foundit) { @@ -856,8 +848,8 @@ ioctl(audiofd, SNDCTL_DSP_GETODELAY, &soundcard_buffer); // bytes totalbuffer = audiolen(false) + soundcard_buffer; - audiotime = audbuf_timecode - (int)((double)totalbuffer * 25000.0 / - (double)effdsp); + audiotime = audbuf_timecode - + (int)(totalbuffer * 100000.0 / (audio_bits_per_sample/8 * audio_channels * effdsp)); gettimeofday(&audiotime_updated, NULL); @@ -993,17 +985,29 @@ do { - lameret = lame_decode(strm, packetlen, pcmlbuffer, - pcmrbuffer); + mp3data_struct header; + lameret = lame_decode_headers(strm, packetlen, pcmlbuffer, + pcmrbuffer, &header); if (lameret > 0) { int itemp = 0; int afree = audiofree(false); - if (lameret * 4 > afree) + if(header.header_parsed && header.stereo != audio_channels && + audio_ioctl_int(audiofd, SNDCTL_DSP_CHANNELS, &(audio_channels=header.stereo), + "audio mp3 output channels") < 0 || + header.header_parsed && header.samplerate != audio_samplerate && + audio_ioctl_int(audiofd, SNDCTL_DSP_SPEED, &(audio_samplerate=header.samplerate), + "audio mp3 output samplerate") < 0) + { + close(audiofd); + audiofd = -1; + } + + if (lameret * audio_channels * audio_bits_per_sample/8 > afree) { - lameret = afree / 4; + lameret = afree / audio_channels / (audio_bits_per_sample/8); cout << "Audio buffer overflow, audio data lost!\n"; } @@ -1011,11 +1015,17 @@ for (itemp = 0; itemp < lameret; itemp++) { - saudbuffer[waud / 2] = pcmlbuffer[itemp]; - saudbuffer[waud / 2 + 1] = pcmrbuffer[itemp]; - - waud += 4; - len += 4; + if(audio_channels == 2) + { + saudbuffer[waud / 2] = pcmlbuffer[itemp]; + saudbuffer[waud / 2 + 1] = pcmrbuffer[itemp]; + } + else + { + saudbuffer[waud] = pcmlbuffer[itemp]; + } + waud += audio_channels * audio_bits_per_sample/8; + len += audio_channels * audio_bits_per_sample/8; if (waud >= AUDBUFSIZE) waud -= AUDBUFSIZE; } @@ -1388,8 +1398,8 @@ /* do audio output */ /* approximate # of audio bytes for each frame. */ - bytesperframe = 4 * (int)((1.0/video_frame_rate) * - ((double)effdsp/100.0) + 0.5); + bytesperframe = (audio_channels * audio_bits_per_sample/8) * + (int)(effdsp / 100.0 / video_frame_rate + 0.5); // wait for the buffer to fill with enough to play if (bytesperframe >= audiolen(true)) Index: libs/libNuppelVideo/NuppelVideoPlayer.h =================================================================== RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoPlayer.h,v retrieving revision 1.48 diff -u -r1.48 NuppelVideoPlayer.h --- libs/libNuppelVideo/NuppelVideoPlayer.h 15 Nov 2002 00:12:07 -0000 1.48 +++ libs/libNuppelVideo/NuppelVideoPlayer.h 19 Nov 2002 10:37:59 -0000 @@ -183,6 +183,8 @@ unsigned char *buf2; char lastct; int effdsp; // from the recorded stream + int audio_channels; // from the recorded stream + int audio_bits_per_sample; // per channel int audio_samplerate; // rate to tell the output device int filesize; int startpos; Index: libs/libNuppelVideo/NuppelVideoRecorder.cpp =================================================================== RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoRecorder.cpp,v retrieving revision 1.62 diff -u -r1.62 NuppelVideoRecorder.cpp --- libs/libNuppelVideo/NuppelVideoRecorder.cpp 18 Nov 2002 01:59:38 -0000 1.62 +++ libs/libNuppelVideo/NuppelVideoRecorder.cpp 19 Nov 2002 10:38:00 -0000 @@ -24,6 +24,21 @@ pthread_mutex_t avcodeclock = PTHREAD_MUTEX_INITIALIZER; +int audio_ioctl_int(int fd, int arg, int *value, const char *decscription) +{ + int ret, orig = *value; + + cout << "setting " << decscription << " to " << *value << endl; + + if ((ret=ioctl(fd, arg, value)) < 0) + cerr << "problem setting " << decscription << ", exiting\n"; + else + if(orig != *value) + cout << decscription << " forced to use " << *value + << " instead of " << orig << endl; + return ret; +} + NuppelVideoRecorder::NuppelVideoRecorder(void) { sfilename = "output.nuv"; @@ -71,6 +86,8 @@ keyframedist = KEYFRAMEDIST; audiobytes = 0; + audio_channels = 2; + audio_bits_per_sample = 16; audio_samplerate = 44100; picture_format = PIX_FMT_YUV420P; @@ -259,6 +276,8 @@ lame_set_bWriteVbrTag(gf, 0); lame_set_quality(gf, mp3quality); lame_set_compression_ratio(gf, 11); + lame_set_mode(gf, audio_channels == 2 ? STEREO : MONO); + lame_set_num_channels(gf, audio_channels); lame_set_out_samplerate(gf, audio_samplerate); lame_set_in_samplerate(gf, audio_samplerate); lame_init_params(gf); @@ -313,5 +332,5 @@ int NuppelVideoRecorder::AudioInit(void) { int afmt, afd; - int frag, channels, rate, blocksize = 4096; + int frag, blocksize = 4096; @@ -331,30 +351,18 @@ if (afmt != AFMT_S16_LE) { cerr << "Can't get 16 bit DSP, exiting\n"; - return(1); - } - - channels = 2; - ioctl(afd, SNDCTL_DSP_CHANNELS, &channels); - - /* sample rate */ - rate = audio_samplerate; - if (ioctl(afd, SNDCTL_DSP_SPEED, &rate) < 0) - { - cerr << "setting sample rate failed, exiting\n"; return 1; } - if (rate != audio_samplerate) - { - cerr << "setting sample rate to " << audio_samplerate << " failed\n"; - return 1; - } + if(audio_ioctl_int(afd, SNDCTL_DSP_CHANNELS, &audio_channels, "audio input channels") < 0 || + audio_ioctl_int(afd, SNDCTL_DSP_SPEED, &audio_samplerate, "audio input samplerate") < 0 || + audio_ioctl_int(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits_per_sample, "audio input bits per sample") < 0) + return 1; if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize)) { cerr << "Can't get DSP blocksize, exiting\n"; - return(1); + return 1; } blocksize *= 4; @@ -1107,8 +1115,8 @@ } moredata.audio_sample_rate = audio_samplerate; - moredata.audio_channels = 2; - moredata.audio_bits_per_sample = 16; + moredata.audio_channels = audio_channels; + moredata.audio_bits_per_sample = audio_bits_per_sample; extendeddataOffset = ringBuffer->GetFileWritePosition(); @@ -1238,8 +1246,8 @@ { int afmt = 0, trigger = 0; int afd = 0, act = 0, lastread = 0; - int frag = 0, channels = 0, rate = 0, blocksize = 0; + int frag = 0, blocksize = 0; unsigned char *buffer; audio_buf_info ispace; struct timeval anow; @@ -1265,12 +1274,13 @@ return; } - channels = 2; - ioctl(afd, SNDCTL_DSP_CHANNELS, &channels); - - /* sample rate */ - rate = audio_samplerate; - ioctl(afd, SNDCTL_DSP_SPEED, &rate); + if(audio_ioctl_int(afd, SNDCTL_DSP_CHANNELS, &audio_channels, "audio input channels") < 0 || + audio_ioctl_int(afd, SNDCTL_DSP_SPEED, &audio_samplerate, "audio input samplerate") < 0 || + audio_ioctl_int(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits_per_sample, "audio input bits per sample") < 0) + { + close(afd); + return; + } if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize)) { @@ -1339,8 +1349,8 @@ /* Back up the timecode. The more stuff is in the hw buffer, the earlier this audio was actually recorded. */ audiobuffer[act]->timecode -= - (int) ( ( (double)ispace.fragments * (double)ispace.fragsize * 1000.0 ) / - ( (double)audio_samplerate * 4.0 ) ); + (int)(ispace.fragments * ispace.fragsize * 1000.0 / + (audio_samplerate * audio_bits_per_sample/8 * audio_channels)); memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size); @@ -1728,12 +1738,12 @@ // wrong guess ;-) // need seconds instead of msec's //mt = (double)timecode/1000.0; - mt = (double)timecode; + mt = timecode; if (mt > 0.0) { //eff = (abytes/4.0)/mt; //effectivedsp=(int)(100.0*eff); - eff = (abytes/mt)*((double)100000.0/(double)4.0); + eff = (abytes/mt)*(100000.0 / (audio_bits_per_sample/8) / audio_channels); effectivedsp=(int)eff; } } @@ -1745,10 +1755,21 @@ int gaplesssize = 0; int lameret = 0; - lameret = lame_encode_buffer_interleaved(gf, (short int *)buf, - audio_buffer_size / 4, - (unsigned char *)mp3buf, - mp3buf_size); + if(audio_channels == 2) + { + lameret = lame_encode_buffer_interleaved(gf, (short int *)buf, + audio_buffer_size / audio_channels / (audio_bits_per_sample/8), + (unsigned char *)mp3buf, + mp3buf_size); + } + else + { + lameret = lame_encode_buffer(gf, (short int *)buf, (short int *)buf, + audio_buffer_size / audio_channels / (audio_bits_per_sample/8), + (unsigned char *)mp3buf, + mp3buf_size); + } + if (lameret < 0) { cerr << "lame error, exiting\n"; Index: libs/libNuppelVideo/NuppelVideoRecorder.h =================================================================== RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoRecorder.h,v retrieving revision 1.25 diff -u -r1.25 NuppelVideoRecorder.h --- libs/libNuppelVideo/NuppelVideoRecorder.h 18 Nov 2002 01:59:38 -0000 1.25 +++ libs/libNuppelVideo/NuppelVideoRecorder.h 19 Nov 2002 10:38:00 -0000 @@ -126,6 +126,8 @@ int compression; int compressaudio; unsigned long long audiobytes; + int audio_channels; // channels to request from sounddevice + int audio_bits_per_sample; // per channel int audio_samplerate; // rate we request from sounddevice int effectivedsp; // actual measured rate
|