/* playing raw data, this proc handels WAVE files and .VOCs (as one block) */ static int do_play (int fd, int loaded, u_long count, int rtype, char *name) { int l, real_l; u_long c; char one_chn = 0; char to_8 = 0; int tmps; sync_dsp (); tmps = samplesize; ioctl (audio, SNDCTL_DSP_SETFMT, &tmps); if (tmps != samplesize) { fprintf (stderr, "Unable to set %d bit sample size", samplesize); if (samplesize == 16) { samplesize = 8; ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize); if (samplesize != 8) { fprintf (stderr, "Unable to set 8 bit sample size!\n"); return -1; } fprintf (stderr, "; playing 8 bit\n"); to_8 = 1; } else { fprintf (stderr, "\n"); return -1; } } #ifdef OSS_VERSION if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0) { #else if (dsp_stereo != ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo)) { #endif fprintf (stderr, "Can't play in Stereo; playing only one channel\n"); dsp_stereo = MODE_MONO; one_chn = 1; } if (set_dsp_speed (&dsp_speed) < 0) return -1; abuf_size = 512; while (count) { c = count; if (c > abuf_size) c = abuf_size; if ((l = read (fd, (char *) audiobuf + loaded, c - loaded)) > 0) { l += loaded; loaded = 0; /* correct the count; ugly but ... */ real_l = (one_chn || to_8) ? one_channel (audiobuf, l, one_chn, to_8) : l; /* change byte order if necessary */ if (convert && (samplesize == 16)) { long i; for (i = 0; i < real_l; i += 2) *((short *) (audiobuf + i)) = htons (*((short *) (audiobuf + i))); } if (write (audio, (char *) audiobuf, real_l) != real_l) { perror (AUDIO); return -1; } count -= l; } else { if (l == -1) { perror (name); return -1; } count = 0; /* Stop */ } } /* while (count) */ return 0; } /* let's play) */ static int player (char *name) { int fd, ofs; if (!name) { fd = 0; name = "stdin"; } else if ((fd = open (name, O_RDONLY, 0)) == -1) { perror (name); return -1; } /* Read the smallest header first, then the missing bytes for the next, etc. */ /* read SND-header */ read (fd, (char *) audiobuf, sizeof (SndHeader)); if (test_sndfile (audiobuf, fd) >= 0) { if (do_play (fd, 0, count, SND_FMT, name) < 0) return -1; } else { /* read VOC-Header */ read (fd, (char *) audiobuf + sizeof (SndHeader), sizeof (VocHeader) - sizeof (SndHeader)); if ((ofs = test_vocfile (audiobuf)) >= 0) { if (vplay (fd, ofs, name) < 0) return -1; } else { /* read bytes for WAVE-header */ read (fd, (char *) audiobuf + sizeof (VocHeader), sizeof (WaveHeader) - sizeof (VocHeader)); if (test_wavefile (audiobuf) >= 0) { if (do_play (fd, 0, count, WAVE_FMT, name) < 0) return -1; } else { /* should be raw data */ init_raw_data (); count = calc_count (); if (do_play (fd, sizeof (WaveHeader), count, RAW_DATA, name) < 0) return -1; } } } if (fd != 0) close (fd); return 0; }
int music::play_music() { MainWindow *mine=(MainWindow*)arg; mine->my_words(); int music_len; long rate; char* buf; long n; int min; min=ftell(music_fp); music_len = head.ChunkSize+8; mine->set_line(music_len,min); ///安装dsp 设置 采样率 声道个数 if(setup_dsp(dsp_fd,head.SampleRate,head.NumChannels) != 0) { perror("setup_dsp failed"); return -1; } ////生效setup_dsp设置 if(sync_dsp(dsp_fd) != 0) { perror("sync dsp failed"); return -1; } //-----设置采样率-------- //采样位数*采样率/8 = 字节数量 //+7 方式采样率不是8的整数倍的情况 // /8*2 = /4 都按照双声道处理 //size = (head.BitsPerSample*head.SampleRate+7)>>2; rate = head.ByteRate; //每次读取的字节 = 字节速率 buf = (char*)malloc(rate); //音乐数据缓存 if(buf != NULL) { do{ pthread_mutex_lock(&my_mutex); pthread_mutex_unlock(&my_mutex); mine->word_move(); n = fread(buf,1,rate,music_fp); //cout<<"n:"<<n<<endl; if(n > 0) { write(dsp_fd,buf,n); } if(feof(music_fp)) { perror("play over."); break; } mine->add_second(); mine->move_line(ftell(music_fp)); this->set_vol(); }while(1); } return 1; }
/* ok, let's play a .voc file */ static int vplay (int fd, int ofs, char *name) { int l, real_l; BlockType *bp; Voice_data *vd; Ext_Block *eb; u_long nextblock, in_buffer; u_char *data = audiobuf; char was_extended = 0, output = 0; u_short *sp, repeat = 0; u_long silence; int filepos = 0; char one_chn = 0; #define COUNT(x) nextblock -= x; in_buffer -=x ;data += x /* first SYNC the dsp */ sync_dsp (); if (!quiet_mode) fprintf (stderr, "Playing Creative Labs Voice file ...\n"); /* first we waste the rest of header, ugly but we don't need seek */ while (ofs > abuf_size) { read (fd, (char *) audiobuf, abuf_size); ofs -= abuf_size; } if (ofs) read (fd, audiobuf, ofs); /* .voc files are 8 bit (now) */ samplesize = VOC_SAMPLESIZE; ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize); if (samplesize != VOC_SAMPLESIZE) { fprintf (stderr, "Unable to set 8 bit sample size!\n"); return -1; } /* and there are MONO by default */ dsp_stereo = MODE_MONO; ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo); in_buffer = nextblock = 0; while (1) { Fill_the_buffer: /* need this for repeat */ if (in_buffer < 32) { /* move the rest of buffer to pos 0 and fill the audiobuf up */ if (in_buffer) memcpy ((char *) audiobuf, data, in_buffer); data = audiobuf; if ((l = read (fd, (char *) audiobuf + in_buffer, abuf_size - in_buffer)) > 0) in_buffer += l; else if (!in_buffer) { /* the file is truncated, so simulate 'Terminator' and reduce the datablock for save landing */ nextblock = audiobuf[0] = 0; if (l == -1) { perror (name); return -1; } } } while (!nextblock) { /* this is a new block */ bp = (BlockType *) data; COUNT (sizeof (BlockType)); nextblock = DATALEN (bp); if (output && !quiet_mode) fprintf (stderr, "\n"); /* write /n after ASCII-out */ output = 0; switch (bp->type) { case 0: d_printf ((stderr, "Terminator\n")); return -1; /* VOC-file stop */ case 1: vd = (Voice_data *) data; COUNT (sizeof (Voice_data)); /* we need a SYNC, before we can set new SPEED, STEREO ... */ sync_dsp (); if (!was_extended) { dsp_speed = (int) (vd->tc); dsp_speed = 1000000 / (256 - dsp_speed); d_printf ((stderr, "Voice data %d Hz\n", dsp_speed)); if (vd->pack) { /* /dev/dsp can't it */ fprintf (stderr, "Can't play packed .voc files\n"); return -1; } if (dsp_stereo) { /* if we are in Stereo-Mode, switch back */ dsp_stereo = MODE_MONO; ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo); } } else { /* there was extended block */ if (one_chn) /* if one Stereo fails, why test another ? */ dsp_stereo = MODE_MONO; else if (dsp_stereo) { /* want Stereo */ /* shit, my MACRO dosn't work here */ #ifdef OSS_VERSION if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0) { #else if (dsp_stereo != ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo)) { #endif dsp_stereo = MODE_MONO; fprintf (stderr, "Can't play in Stereo; playing only one channel\n"); one_chn = 1; } } was_extended = 0; } if (set_dsp_speed (&dsp_speed) < 0) return -1; break; case 2: /* nothing to do, pure data */ d_printf ((stderr, "Voice continuation\n")); break; case 3: /* a silence block, no data, only a count */ sp = (u_short *) data; COUNT (sizeof (u_short)); dsp_speed = (int) (*data); COUNT (1); dsp_speed = 1000000 / (256 - dsp_speed); sync_dsp (); if (set_dsp_speed (&dsp_speed) < 0) return -1; silence = (((u_long) * sp) * 1000) / dsp_speed; d_printf ((stderr, "Silence for %ld ms\n", silence)); break; case 4: /* a marker for syncronisation, no effect */ sp = (u_short *) data; COUNT (sizeof (u_short)); d_printf ((stderr, "Marker %d\n", *sp)); break; case 5: /* ASCII text, we copy to stderr */ output = 1; d_printf ((stderr, "ASCII - text :\n")); break; case 6: /* repeat marker, says repeatcount */ /* my specs don't say it: maybe this can be recursive, but I don't think somebody use it */ repeat = *(u_short *) data; COUNT (sizeof (u_short)); d_printf ((stderr, "Repeat loop %d times\n", repeat)); if (filepos >= 0) /* if < 0, one seek fails, why test another */ if ((filepos = lseek (fd, 0, 1)) < 0) { fprintf (stderr, "Can't play loops; %s isn't seekable\n", name); repeat = 0; } else filepos -= in_buffer; /* set filepos after repeat */ else repeat = 0; break; case 7: /* ok, lets repeat that be rewinding tape */ if (repeat) { if (repeat != 0xFFFF) { d_printf ((stderr, "Repeat loop %d\n", repeat)); --repeat; } else d_printf ((stderr, "Neverending loop\n")); lseek (fd, filepos, 0); in_buffer = 0; /* clear the buffer */ goto Fill_the_buffer; } else d_printf ((stderr, "End repeat loop\n")); break; case 8: /* the extension to play Stereo, I have SB 1.0 :-( */ was_extended = 1; eb = (Ext_Block *) data; COUNT (sizeof (Ext_Block)); dsp_speed = (int) (eb->tc); dsp_speed = 256000000L / (65536 - dsp_speed); dsp_stereo = eb->mode; if (dsp_stereo == MODE_STEREO) dsp_speed = dsp_speed >> 1; if (eb->pack) { /* /dev/dsp can't it */ fprintf (stderr, "Can't play packed .voc files\n"); return -1; } d_printf ((stderr, "Extended block %s %d Hz\n", (eb->mode ? "Stereo" : "Mono"), dsp_speed)); break; default: fprintf (stderr, "Unknown blocktype %d. terminate.\n", bp->type); return -1; } /* switch (bp->type) */ } /* while (! nextblock) */ /* put nextblock data bytes to dsp */ l = min (in_buffer, nextblock); if (l) { if (output && !quiet_mode) write (2, data, l); /* to stderr */ else { real_l = one_chn ? one_channel (data, l, one_chn, 0) : l; if (write (audio, data, real_l) != real_l) { perror (AUDIO); return -1; } } COUNT (l); } } /* while(1) */ } /* that was a big one, perhaps somebody split it :-) */ /* setting the globals for playing raw data */ static void init_raw_data (void) { timelimit = raw_info.timelimit; dsp_speed = raw_info.dsp_speed; dsp_stereo = raw_info.dsp_stereo; samplesize = raw_info.samplesize; }