?? buffer.cpp
字號:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <qobject.h>#include <qlistbox.h>#include <kmessagebox.h>#include <klocale.h>#include "byteorder.h"#include "sound.h"#include "buffer.moc"extern KLocale *globalKlocale;/* ---------------------------------------------------------------------- */voidxperror(const char *msg){ char text[256]; sprintf(text,"%s: %s", msg, strerror(errno)); KMessageBox::error(NULL, text);}/* ---------------------------------------------------------------------- */AudioBuffer::AudioBuffer(){ size = 0; busy = 0; position = 0; clippedsamples = 0;}AudioBuffer::~AudioBuffer() {}int AudioBuffer::is_busy() { return busy; }void AudioBuffer::balloc(void){ busy++; if (busy != 1) fprintf(stderr,"alloc: buffer reference count bug: %d\n",busy);}void AudioBuffer::bfree(void){ busy--; if (busy != 0) fprintf(stderr,"free: buffer reference count bug: %d\n",busy);}int AudioBuffer::start_write(struct SOUNDPARAMS*) { return 0; }void AudioBuffer::stop_write() {}struct SOUNDPARAMS* AudioBuffer::get_params() { return NULL; }int AudioBuffer::get_size() { return 0; }char* AudioBuffer::name() { return NULL; }void* AudioBuffer::read_audio(int len) { return 0; }int AudioBuffer::write_audio(int len, void *data) { return 0; }int AudioBuffer::seek(int pos) { return 0; }int AudioBuffer::tell() { return 0; }/* ---------------------------------------------------------------------- */#define BUFFER_SIZE 0x10000#define BUFFER_MASK 0x0ffff#define BUFFER_SHIFT 16RAMBuffer::RAMBuffer(){ static int counter = 0; memset(¶ms,0,sizeof(struct SOUNDPARAMS)); sprintf(bufname,"buffer #%d",++counter); buffers = (char**)malloc(sizeof(void*)); buffers[0] = (char*)malloc(BUFFER_SIZE); bufcount = 1; position = 0;}RAMBuffer::~RAMBuffer(){ int i; for (i = 0; i < bufcount; i++) { free(buffers[i]); } free(buffers);}intRAMBuffer::start_write(struct SOUNDPARAMS *p){ memcpy(¶ms,p,sizeof(struct SOUNDPARAMS)); return 0;}void RAMBuffer::stop_write() {};struct SOUNDPARAMS*RAMBuffer::get_params(){ return ¶ms;}intRAMBuffer::get_size(){ return size;}char*RAMBuffer::name(){ return bufname;}void*RAMBuffer::read_audio(int len){ /* FIXME (?): one can't read over buffer boundaries */ char *ptr; if (position+len > size) return NULL; ptr = buffers[position>>BUFFER_SHIFT]; ptr += (position&BUFFER_MASK); position += len; return ptr;}intRAMBuffer::write_audio(int len, void *data){ /* dito for write - not over buffer boundaries */ if ((position>>BUFFER_SHIFT) >= bufcount) { buffers = (char**)realloc(buffers,sizeof(void*)*(bufcount+1)); if (NULL == (buffers[bufcount] = (char*)malloc(BUFFER_SIZE))) return -1; bufcount++; } memcpy(buffers[position>>BUFFER_SHIFT]+(position&BUFFER_MASK), data, len); position += len; if (size < position) size = position; return 0;}intRAMBuffer::seek(int pos){ if (pos > size) return -1; position = pos; return position;}intRAMBuffer::tell(){ return position;}/* ---------------------------------------------------------------------- */FileBuffer::FileBuffer(){ memset(¶ms,0,sizeof(struct SOUNDPARAMS)); fd = -1; size = position = 0; bstart = bstop = 0;}FileBuffer::~FileBuffer(){ if (fd == -1) return; close(fd);}voidFileBuffer::init_header(){ /* stolen from cdda2wav */ int nBitsPerSample = 8; if (params.format == FMT_16BIT) nBitsPerSample = 16; unsigned long nBlockAlign = params.channels * ((nBitsPerSample + 7) / 8); unsigned long nAvgBytesPerSec = nBlockAlign * params.rate; unsigned long temp = /* data length */ 0 + sizeof(WAVEHDR) - sizeof(CHUNKHDR); fileheader.chkRiff.ckid = cpu_to_le32(FOURCC_RIFF); fileheader.fccWave = cpu_to_le32(FOURCC_WAVE); fileheader.chkFmt.ckid = cpu_to_le32(FOURCC_FMT); fileheader.chkFmt.dwSize = cpu_to_le32(16); fileheader.wFormatTag = cpu_to_le16(WAVE_FORMAT_PCM); fileheader.nChannels = cpu_to_le16(params.channels); fileheader.nSamplesPerSec = cpu_to_le32(params.rate); fileheader.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec); fileheader.nBlockAlign = cpu_to_le16(nBlockAlign); fileheader.wBitsPerSample = cpu_to_le16(nBitsPerSample); fileheader.chkData.ckid = cpu_to_le32(FOURCC_DATA); fileheader.chkRiff.dwSize = cpu_to_le32(temp); fileheader.chkData.dwSize = cpu_to_le32(0 /* data length */);}intFileBuffer::attach(const char *file){ int new_file = 0; if (-1 != fd) close(fd); ro = 0; position = 0; size = 0; offset = sizeof(WAVEHDR); strcpy(filename,file); if (-1 == (fd = open(filename,O_RDWR))) { if (errno == ENOENT) { if (-1 == (fd = open(filename,O_RDWR|O_CREAT,0666))) { xperror(i18n("can't create wav file")); return -1; } new_file = 1; } else { if (-1 == (fd = open(filename,O_RDONLY))) { xperror(i18n("can't open wav file")); return -1; } else ro = 1; } } fcntl(fd,F_SETFD,FD_CLOEXEC); if (!new_file) { read(fd,&fileheader,offset); if (!IS_STD_WAV_HEADER(fileheader)) {#if 0 /* nice for debugging, but annonying for everyday usage */ KMessageBox::error(NULL, i18n("not a wav file"));#endif return -1; } if (le16_to_cpu(fileheader.wFormatTag) != WAVE_FORMAT_PCM) { KMessageBox::error(NULL,i18n("unsupported audio format")); return -1; } params.format = FMT_8BIT; if (16 == le16_to_cpu(fileheader.wBitsPerSample)) params.format = FMT_16BIT; params.channels = le16_to_cpu(fileheader.nChannels); params.rate = cpu_to_le32(fileheader.nSamplesPerSec); size = le32_to_cpu(fileheader.chkData.dwSize); } return 0;}intFileBuffer::start_write(struct SOUNDPARAMS *p){ memcpy(¶ms,p,sizeof(struct SOUNDPARAMS)); init_header(); lseek(fd,0,SEEK_SET); write(fd,&fileheader,offset); return 0;}voidFileBuffer::stop_write(){ unsigned long temp = size + sizeof(WAVEHDR) - sizeof(CHUNKHDR); fileheader.chkRiff.dwSize = cpu_to_le32(temp); fileheader.chkData.dwSize = cpu_to_le32(size); lseek(fd,0,SEEK_SET); write(fd,&fileheader,offset);}struct SOUNDPARAMS*FileBuffer::get_params(){ return ¶ms;}intFileBuffer::get_size(){ return size;}char*FileBuffer::name(){ return filename;}void*FileBuffer::read_audio(int len){ int rc; if (position+len > size) return NULL; /* printf("[%d - %d (+%d) - %d] / %d\n",bstart,position,len,bstop,size); */ if (position < bstart || position+len > bstop) { rc = read(fd,buffer,65536);#if BYTE_ORDER == BIG_ENDIAN if (params.format == FMT_16BIT) { /* byteswap 16bit pcm on bigendian machines */ int i; char h; for (i = 0; i < rc; i += 2) { h = buffer[i]; buffer[i] = buffer[i+1]; buffer[i+1] = h; } }#endif if (-1 == rc) return NULL; bstart = position, bstop = position+rc; } position += len; return buffer+position-bstart-len;}intFileBuffer::write_audio(int len, void *data){ int rc;#if BYTE_ORDER == BIG_ENDIAN char *buf; int i; if (params.format == FMT_16BIT) { /* byteswap 16bit pcm on bigendian machines */ buf = (char*)malloc(len); for (i = 0; i < len; i += 2) { buf[i] = ((char*)data)[i+1]; buf[i+1] = ((char*)data)[i]; } rc = write(fd,buf,len); free(buf); } else { rc = write(fd,data,len); }#else rc = write(fd,data,len);#endif if (len == rc) { position += len; if (position > size) size = position; return 0; } else return -1;}intFileBuffer::seek(int pos){ if (pos > size) return -1; position = pos; if (-1 == lseek(fd,position+offset,SEEK_SET)) perror("fb: lseek"); return 0;}intFileBuffer::tell(){ return position;}/* ---------------------------------------------------------------------- */BufferList::BufferList(QListBox *l, Soundcard *c){ listbox = l; card = c; count = 0; brecord = -1; bplayback = -1; mon = 0; level = 0; wait = 0; new_buffer_count = 0; connect(card,SIGNAL(newparams(struct SOUNDPARAMS*)), this, SLOT(new_params(struct SOUNDPARAMS*))); connect(card,SIGNAL(senddata(void*)), this, SLOT(new_data(void*))); connect(card,SIGNAL(receivedata(void*)), this, SLOT(post_data(void*)));}intBufferList::add_filebuffer(const char *filename){ FileBuffer *fbuffer; fbuffer = new FileBuffer(); if (-1 == fbuffer->attach(filename)) { delete fbuffer; return -1; } add_buffer(fbuffer); return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -