?? srec.cc
字號:
/* * wavrec/mpegrec for Linux ( Direct-to-disk WAV file and MP3 capture ) * ( MP3 is available via lame: www.sulaco.org/mp3 ) * Developed by Andrew L. Sandoval -- sandoval@netwaysglobal.com -- Feb. 2000 * * Copyright (C) 2000 Andrew L. Sandoval * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <iostream>#include <string>#include <vector>#include <deque>#include <cstring>#include <map>extern "C"{ #include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/soundcard.h> #include <pthread.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <errno.h>}#define BUFFER_SIZE 65535#define MIN_BUFFERS 10struct SndBuffer{ unsigned long used; unsigned char buffer[BUFFER_SIZE];};#define WAV_ID_RIFF 0x46464952 /* "RIFF" */#define WAV_ID_WAVE 0x45564157 /* "WAVE" */#define WAV_ID_FMT 0x20746d66 /* "fmt " */#define WAV_ID_DATA 0x61746164 /* "data" */#define WAV_ID_PCM 0x0001struct WaveHeader{ unsigned long riff; unsigned long file_length; unsigned long wave; unsigned long fmt; unsigned long fmt_length; short fmt_tag; short channels; unsigned long sample_rate; unsigned long bytes_per_second; short block_align; short bits; unsigned long data; unsigned long data_length;};struct WaveHeader genericWaveHeader = { WAV_ID_RIFF, 0xFFFFFFFF, WAV_ID_WAVE, WAV_ID_FMT, 16, WAV_ID_PCM, 2, 44100, 192000, 4, 16, WAV_ID_DATA, 0xFFFFFFFF };deque <struct SndBuffer *> inputBuffers;deque <struct SndBuffer *> fullBuffers;unsigned long seconds = 0; //Ctrl-C to stopunsigned long bytesPerSecond = 44100 * 2 *2;int recordingNow = 0;int doneRecording = 0;int stopRequested = 0;int binitialized = 0;pthread_mutex_t fullBuffersLock = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t inputBuffersLock = PTHREAD_MUTEX_INITIALIZER;int outputFd = 1;static void stop(int signal){ stopRequested++;}unsigned long shipToEncoder(unsigned long *processed){ unsigned long lastSize; pthread_mutex_lock( &fullBuffersLock ); lastSize = fullBuffers.size(); if(!lastSize) { pthread_mutex_unlock( &fullBuffersLock ); if(processed) *processed = 0; return lastSize; } struct SndBuffer *sndbuf = fullBuffers[0]; fullBuffers.pop_front(); pthread_mutex_unlock( &fullBuffersLock ); write( outputFd, reinterpret_cast<void*>(sndbuf->buffer), sndbuf->used ); if(processed) *processed = sndbuf->used; lastSize--; delete sndbuf; return lastSize;}static void *encode(void *arg){ unsigned long lastSize = 1; unsigned long bytesProcessed = 0; unsigned long Processed = 0; while(!doneRecording || lastSize) { lastSize = shipToEncoder(&Processed); bytesProcessed += Processed; if( bytesProcessed > (bytesPerSecond /2) ) { cerr << "."; bytesProcessed = 0; } if(!lastSize) { sched_yield(); continue; } }}static void *prepareBuffers(void *arg){ while(1) { // Prepare enough input buffers for one second: unsigned long onesecond = bytesPerSecond / BUFFER_SIZE; onesecond++; for(int i=0; i < onesecond; i++) { struct SndBuffer *buffer = new SndBuffer; memset( reinterpret_cast<void*>(buffer), 0, sizeof(SndBuffer) ); pthread_mutex_lock( &inputBuffersLock ); inputBuffers.push_back( buffer ); pthread_mutex_unlock( &inputBuffersLock ); } pthread_mutex_lock( &inputBuffersLock ); unsigned long sz = inputBuffers.size(); pthread_mutex_unlock( &inputBuffersLock ); binitialized = 1; while(sz > MIN_BUFFERS) { sched_yield(); pthread_mutex_lock( &inputBuffersLock ); sz = inputBuffers.size(); pthread_mutex_unlock( &inputBuffersLock ); } } return NULL;}int main(int argc, char *argv[]){ unsigned long rate = 44100; char *mpg_bitrate = "192"; unsigned long argument_error = 0; string outputFile = "-"; string encoderProcess = "lame"; string encoderExtraFlags = ""; int userSuppliedEncoder = 0; int userSuppliedEncoderExtras = 0; FILE *lame_encoder = NULL; int mpegrec = 0; if(strstr(argv[0], "mpegrec")) mpegrec++; cerr << argv[0] << " Copyright (C) 2000 Andrew L. Sandoval" << endl << "This program comes with ABSOLUTELY NO WARRANTY." << endl << "See the file COPYING (http://www.gnu.org/copyleft/gpl.txt) for details." << endl << endl; for(int i=1; i<argc; i++) { if(!strcmp(argv[i], "-l") && argc>i) { seconds = atol(argv[i+1]); ++i; continue; } if(!strcmp(argv[i], "-r") && argc>1) { rate = atol(argv[i+1]); ++i; continue; } if(!strcmp(argv[i], "-e") && argc>1) { encoderProcess = string(argv[i+1]); userSuppliedEncoder = 1; ++i; continue; } if(!strcmp(argv[i], "-x") && argc>1) { encoderExtraFlags = string(argv[i+1]); userSuppliedEncoderExtras = 1; ++i; continue; } if(!strcmp(argv[i], "-o") && argc>1) { outputFile = string(argv[i+1]); ++i; continue; } if(!strcmp(argv[i], "-b") && argc>1) { mpg_bitrate = argv[i+1]; ++i; continue; } if(!strcmp(argv[i], "--help") || !strcmp(argv[i], "-?")) { argument_error++; break; } cerr << "Unknown argument: '" << argv[i] << "'" << endl; argument_error++; } if(argument_error) { cerr << endl << "USAGE: " << argv[0] << " [options]" << endl << "Options:" << endl << " -b mp3_bitrate_in_kHz (for mpegrec only - default is 192)" << endl << " -e encoder_process (for mpegrec only - default is \"lame\")" << endl << " -l length_in_seconds (default is to continue until ctrl-c)" << endl << " -r rate (default is 44100)" << endl << " -o outputfilename (default is stdout or \"-\")" << endl << " -x extraEncoderFlags (default is \"\")" << endl << endl; return 1; } bytesPerSecond = rate * 2 * 2; // rate * 16-bits * stereo genericWaveHeader.sample_rate = rate; genericWaveHeader.bytes_per_second = bytesPerSecond; unsigned long hdrSeconds = seconds ? seconds : 3600 * 24; //24hr Max. genericWaveHeader.data_length = bytesPerSecond * (hdrSeconds + 1); genericWaveHeader.file_length = genericWaveHeader.data_length + sizeof(genericWaveHeader); // Setup the signal handler so we stop on CTRL-C signal( SIGHUP, stop ); signal( SIGINT, stop ); signal( SIGQUIT, stop ); signal( SIGTERM, stop ); signal( SIGPIPE, stop ); // Start the buffer supply thread... pthread_t prepbufThread; pthread_create( &prepbufThread, NULL, prepareBuffers, NULL); while( !binitialized ) sched_yield(); //Give prepareBuffers a chance // Begin recording and continue until recordingNow = 0 or bytes of input // equals seconds requested... unsigned long totalBytesRequested = 0; if(seconds) totalBytesRequested = seconds * bytesPerSecond; // If output file is specified and this is NOT an argument of mpegrec // open the output file: if(!mpegrec) { if( outputFile != string("-") ) { outputFd = open( outputFile.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644 ); if(outputFd == -1) { perror( outputFile.c_str() ); return 1; } } } else // mpegrec: { if(!userSuppliedEncoder) { encoderProcess += " -ms -b "; encoderProcess += mpg_bitrate; if(userSuppliedEncoderExtras) { encoderProcess += " "; encoderProcess += encoderExtraFlags; } encoderProcess += " - "; encoderProcess += outputFile; } else { if(userSuppliedEncoderExtras) { encoderProcess += " "; encoderProcess += encoderExtraFlags; } } cerr << "Streaming " << rate << "Hz WAV data to:" << endl << encoderProcess << endl << flush; lame_encoder = popen( encoderProcess.c_str(), "w" ); if(!lame_encoder) { perror( encoderProcess.c_str() ); return 1; } outputFd = fileno( lame_encoder ); } // // Open the sound card // int dsp = open( "/dev/dsp", O_RDONLY ); if(dsp == -1) { perror( "/dev/dsp" ); return 1; } // Reset the card, set the format, stereo, and speed... ioctl( dsp, SNDCTL_DSP_RESET, 0); int format = AFMT_S16_LE; if( ioctl(dsp, SNDCTL_DSP_SETFMT, &format) == -1) { perror( "SNDCTL_DSP_SETFMT" ); return 1; } int stereo = 1; if( ioctl(dsp, SNDCTL_DSP_STEREO, &stereo) == -1) { perror( "SNDCTL_DSP_STEREO" ); return 1; } int samplerate = rate; if( ioctl(dsp, SNDCTL_DSP_SPEED, &samplerate) == -1) { perror( "SNDCTL_DSP_SPEED" ); return 1; } // // Begin Recording... // cerr << endl; recordingNow = 1; // // Write the WAV Header (generic because the length is MAX) // write( outputFd, reinterpret_cast<void*>(&genericWaveHeader), sizeof(genericWaveHeader) ); // Start the encode supply thread... pthread_t encodeThread; pthread_create( &encodeThread, NULL, encode, NULL); unsigned long bytesRead = 0; while(1) { pthread_mutex_lock( &inputBuffersLock ); struct SndBuffer *buf = inputBuffers[0]; if(!buf) { pthread_mutex_unlock( &inputBuffersLock ); cerr << "No inputBuffers!" << endl; buf = new SndBuffer; buf->used = 0; } else inputBuffers.pop_front(); pthread_mutex_unlock( &inputBuffersLock ); buf->used = read( dsp, reinterpret_cast<void*>(buf->buffer), BUFFER_SIZE ); bytesRead += buf->used; pthread_mutex_lock( &fullBuffersLock ); fullBuffers.push_back( buf ); pthread_mutex_unlock( &fullBuffersLock ); if( stopRequested ) break; if(seconds && bytesRead > totalBytesRequested) break; } recordingNow = 0; doneRecording = 1; // Reset the card ioctl( dsp, SNDCTL_DSP_RESET, 0); close( dsp ); pthread_join( encodeThread, NULL ); //Do NOT exit until output is written while(shipToEncoder(NULL)) ; cerr << endl << "Total Bytes Recorded before encoding: " << bytesRead << endl; while(shipToEncoder(NULL)) ; if(!mpegrec) close(outputFd); else pclose( lame_encoder ); return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -