📄 soundstream.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 Opaque Industries - http://www.opaque.net/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* $Id: soundstream.c,v 1.41 2008/09/08 10:20:34 krechert Exp $ */#include <stdlib.h>#include <stdio.h>#include <math.h>#include <limits.h>#include "block.h"#include "soundstream.h"#include "output.h"#include "outputblock.h"#include "character.h"#include "method.h"#include "input.h"#include "libming.h"#include "flv.h"#include "error.h"#include "mp3.h"#include "sound.h"#ifndef round #define round#endif#define STREAM_MP3 1#define STREAM_FLV 2struct StreamSourceMp3{ int start; SWFInput input;};struct StreamSourceFlv{ FLVStream *stream; FLVTag tag; int tagOffset;};#define AUDIO_CODEC(__stream) (((__stream)->flags & 0xf0) >> 4)struct SWFSoundStream_s{ byte isFinished; byte streamSource; int initialDelay; int delay; int samplesPerFrame; int sampleRate; byte freeInput; float frameRate; int flags; union { /* either an MP3 file -> handled by SWFInput */ struct StreamSourceMp3 mp3; /* or FLV stream -> handled by generic flv reader */ struct StreamSourceFlv flv; } source;};struct SWFSoundStreamBlock_s{ struct SWFBlock_s block; SWFSoundStream stream; int numSamples; int delay; int length;};void skipMP3(SWFSoundStream stream, float skip) { int frameSize; int skipFrames, l; if ( stream->sampleRate > 32000 ) frameSize = 1152; else frameSize = 576; skipFrames = (int)floor((skip / frameSize) / stream->sampleRate); if(skipFrames <= 0) return; while(skipFrames > 0) { l = nextMP3Frame(stream->source.mp3.input); if (l < 0) { SWF_warn("no more frames to skip \n"); break; } --skipFrames; stream->source.mp3.start += l; }}intcompleteSWFSoundStream(SWFBlock block){ SWFSoundStreamBlock streamblock = (SWFSoundStreamBlock)block; if(streamblock->stream->streamSource == STREAM_MP3 || AUDIO_CODEC(streamblock->stream) == AUDIO_CODEC_MP3) return streamblock->length + 4; else return streamblock->length;}static void write_flv(SWFSoundStreamBlock streamblock, SWFByteOutputMethod method, void *data){ SWFInput input; FLVStream *flv = streamblock->stream->source.flv.stream; FLVTag *tag = &streamblock->stream->source.flv.tag; int tagOffset = streamblock->stream->source.flv.tagOffset; int l = streamblock->length; int ret; if(tagOffset < 0) { ret = FLVStream_nextTagType(flv, tag, NULL, FLV_AUDIOTAG); if(ret < 0) return; } input = FLVTag_getPayloadInput(tag); if(input == NULL) return; if(tagOffset > 0) SWFInput_seek(input, tagOffset, SEEK_SET); while( l>0 ) { int ichar = SWFInput_getChar(input); if(ichar != EOF) { method(ichar, data); l--; continue; } ret = FLVStream_nextTagType(flv, tag, tag, FLV_AUDIOTAG); if(ret < 0) return; input = FLVTag_getPayloadInput(tag); if(input == NULL) return; } streamblock->stream->source.flv.tag = *tag; streamblock->stream->source.flv.tagOffset = SWFInput_tell(input);}static void write_mp3(SWFSoundStreamBlock streamblock, SWFByteOutputMethod method, void *data){ SWFInput input = streamblock->stream->source.mp3.input; int l = streamblock->length; for ( ; l>0; --l ) method((unsigned char)SWFInput_getChar(input), data);}voidwriteSWFSoundStreamToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFSoundStreamBlock streamblock = (SWFSoundStreamBlock)block; int source = streamblock->stream->streamSource; if(source == STREAM_MP3) { methodWriteUInt16(streamblock->numSamples, method, data); methodWriteUInt16(streamblock->delay, method, data); write_mp3(streamblock, method, data); } else if(source == STREAM_FLV) { if(AUDIO_CODEC(streamblock->stream) == AUDIO_CODEC_MP3) { methodWriteUInt16(streamblock->numSamples, method, data); methodWriteUInt16(streamblock->delay, method, data); } write_flv(streamblock, method, data); }}static intfillBlock_flv_mp3(SWFSoundStream stream, SWFSoundStreamBlock block){ FLVStream *flv = stream->source.flv.stream; FLVTag *tag = &stream->source.flv.tag; int tagOffset = stream->source.flv.tagOffset; int delay, length, frameSize, ret; SWFInput input; block->delay = stream->delay; delay = stream->delay + stream->samplesPerFrame; if(tagOffset < 0) { ret = FLVStream_nextTagType(flv, tag, NULL, FLV_AUDIOTAG); if(ret < 0) { SWF_warn("fillStreamBlock_flv: not a valid flv audio stream\n"); return -1; } } input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; if(tagOffset > 0) SWFInput_seek(input, tagOffset, SEEK_SET); if ( stream->sampleRate > 32000 ) frameSize = 1152; else frameSize = 576; while ( delay > frameSize) { length = nextMP3Frame(input); if (length < 0) { SWF_warn("parse error: not a valid mp3 frame\n"); return -1; } else if(length == 0) /* eof */ { ret = FLVStream_nextTagType(flv, tag, tag, FLV_AUDIOTAG); if(ret < 0) return -1; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; } else { block->numSamples += frameSize; block->length += length; delay -= frameSize; } } stream->source.flv.tag = *tag; stream->source.flv.tagOffset = SWFInput_tell(input); stream->delay = delay; return 0;}static intfillBlock_flv_nelly(SWFSoundStream stream, SWFSoundStreamBlock block){ FLVStream *flv = stream->source.flv.stream; FLVTag *tag = &stream->source.flv.tag; int length, samples, ret; SWFInput input; int tagOffset = stream->source.flv.tagOffset; if(tagOffset < 0) { ret = FLVStream_nextTagType(flv, tag, NULL, FLV_AUDIOTAG); if(ret < 0) { SWF_warn("fillStreamBlock_flv: not a valid flv audio stream\n"); return -1; } } input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; samples = stream->samplesPerFrame; while (samples > 0) { length = SWFInput_length(input); if (length < 0) return -1; samples -= length * 64; block->length += length; if(samples > 0) { ret = FLVStream_nextTagType(flv, tag, tag, FLV_AUDIOTAG); if(ret < 0) return -1; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; } } stream->source.flv.tag = *tag; stream->source.flv.tagOffset = 0; return 0;}static void fillStreamBlock_flv(SWFSoundStream stream, SWFSoundStreamBlock block){ int ret; if(AUDIO_CODEC(stream) == AUDIO_CODEC_MP3) ret = fillBlock_flv_mp3(stream, block); else if(AUDIO_CODEC(stream) == AUDIO_CODEC_NELLY || AUDIO_CODEC(stream) == AUDIO_CODEC_NELLY_MONO) ret = fillBlock_flv_nelly(stream, block); else { SWF_warn("unsupported codec %i\n", AUDIO_CODEC(stream)); ret = -1; } if(ret < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -