PDA

View Full Version : سوال: merge كردن چند فايل wav ؟



Afshin160
چهارشنبه 25 فروردین 1389, 15:43 عصر
با سلام ...

يه سوال چطور ميتونم مثلا" 15 تا فايل 12 ثانيه اي با فرمت Wav را به ترتيب پشت سر هم قرار ميدهم در يك فايل ؟
يعني 15 فايل مي شود يك فايل Wav .

mehdi.mousavi
چهارشنبه 25 فروردین 1389, 16:56 عصر
با سلام ... يه سوال چطور ميتونم مثلا" 15 تا فايل 12 ثانيه اي با فرمت Wav را به ترتيب پشت سر هم قرار ميدهم در يك فايل ؟يعني 15 فايل مي شود يك فايل Wav .

سلام.
من اینکارو تو محیط Managed قبلا انجام نداده ام، اما در محیط Native بکمک DirectShow و Filter Graph ها میشه عملیات Merge چند Stream رو انجام داد. توصیه من نوشتن یه COM Server برای اینکار بزبان C++ و با استفاده از DirectShow Filter ها و استفاده اون از طریق COM InterOp در C# هستش.

البته می تونید به پروژه های DirectShow.Net (http://www.codeproject.com/cs/media/directshownet.asp) و DirectShow.NET Library (http://directshownet.sourceforge.net/) مراجعه کنید که ظاهرا دسترسی Managed به همون API ها رو فراهم میکنه، اما چون من تجربه ای در محیط Managed برای اینکار ندارم، خودتون باید خوب/بد بودن این Framework ها رو محک بزنید.

در نهایت می تونید این سایت (http://kristoffer.vinther.name/projects/managed-directshow/) رو هم ببینید. شاید کمکتون کنه.

موفق باشید.

Afshin160
پنج شنبه 26 فروردین 1389, 09:48 صبح
با سلام ..
دوست عزيز نظرتون در رابطه با ايجاد يه فايل wave جديد كه در برگيرنده header فايلهاي ديگه باشه چيه .؟
يعني براساس ساختار header هر فايل اطلاعات را بيت به بيت خوانده و header جديد ايجاد كرده و بعد اطلاعات
فايل هارا پشت سر هم قرار دهيم

mehdi.mousavi
پنج شنبه 26 فروردین 1389, 10:01 صبح
با سلام .. دوست عزيز نظرتون در رابطه با ايجاد يه فايل wave جديد كه در برگيرنده header فايلهاي ديگه باشه چيه .؟ يعني براساس ساختار header هر فايل اطلاعات را بيت به بيت خوانده و header جديد ايجاد كرده و بعد اطلاعات فايل هارا پشت سر هم قرار دهيم

سلام.
اینکار بستگی داره که دقیقا فرمت فایل Wave اتون چی باشه. در حالتیکه فرمت فایل CCITT A-law یا CCITT u-Law باشه (ای لا و میولا تلفظ میشن)، این کار دشوار نیست. اما در صورتیکه فرمت مزبور MP3، WMA1-2 و چندتای دیگه باشه، اینکار واقعا زمانبر هستش. مگر اینکه Library ای پیدا کنید که تعامل با این فرمت ها رو براتون به ارمغان بیاره. چون همونطور که اطلاع دارید، فایلهای WAV خودشون میتونن 10-12 گونه فرمت داشته باشن...

موفق باشید.

Afshin160
پنج شنبه 26 فروردین 1389, 10:24 صبح
سلام ..
ممنون از پيگيريتون ...امكانش هست به لينك هاي زير يه نگاهي بكنيد
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
http://msdn.microsoft.com/en-us/library/ee419050%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/ms717060%28v=VS.85%29.aspx

درضمن من منظور شما را در رابطه با فرمت هاي مختلف خود فايل wave اصلا" متوجه نشدم .
يعني چي ؟ هر فرمت يه ساختار خواص خود را دارد حال اگر قرارباشه اين ساختار مدل هاي متفاوتي داشته باشد ديگه معناي اصلي خودش را از دست ميدهد .
متشكر ميشم راهنماي كنيد .

mehdi.mousavi
پنج شنبه 26 فروردین 1389, 10:39 صبح
سلام ..
ممنون از پيگيريتون ...امكانش هست به لينك هاي زير يه نگاهي بكنيد
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
http://msdn.microsoft.com/en-us/library/ee419050%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/ms717060%28v=VS.85%29.aspx

درضمن من منظور شما را در رابطه با فرمت هاي مختلف خود فايل wave اصلا" متوجه نشدم .
يعني چي ؟ هر فرمت يه ساختار خواص خود را دارد حال اگر قرارباشه اين ساختار مدل هاي متفاوتي داشته باشد ديگه معناي اصلي خودش را از دست ميدهد .
متشكر ميشم راهنماي كنيد .

سلام.
من این لینکها رو سریع نگاه کردم (لینک اول رو 5-6 سال پیش خونده بودم). اگر به لینک اول نگاه کنید، فرمت فایلهای WAV ای که صوت رو بصورت PCM ذخیره میکنن، ذکر کرده. ببینید. شما گول دنباله فایل رو نخورید.

فایلی با دنباله WAV در واقعیت میتونه PCM، A-Law، u-Law، mp3، WMA1-2 و ... باشه. اگر فرمت فایلهای WAV مورد نظر شما PCM باشه، لینک اول بهتون کمک میکنه که اون ایده رو پیش ببرید و کارتون رو انجام بدید. اما اگر MP3 باشه، نحوه Encode/Decode کردن فایلهای MP3 متفاوته. البته قدیما DLL ای بود به اسم Lame Encoder (اگر دقیق یادم بیاد اسمش رو) که برای Decode کردن فایلهای MP3 بکار برده میشد (Open Source هم بود). در واقع، Player ها از روی Header فایل تشخیص میدن که به چه Codec ای برای پخش یک فایل WAV (بطور مثال) نیاز هستش.

توی سیستمهای مخابراتی، CCITT A-Law و CCITT u-Law دو فرمتی هستن که استفاده میشن، چون Sampling اش برای عبور از زوج سیم کافیه و نیازی به کیفیت MP3 نیست. شما باید بسته به کاری که میخواهید انجام بدید، (اگر بخواهید روش پیشنهادی خودتون رو پیش ببرید)، باید محدوده کاری رو کوچک کنید تا بتونید موضوع رو حل کنید. و الا نوشتن N تا Codec برای تعامل با این فرمتها خودش یک پروژه عظیمی محسوب میشه.

موفق باشید.

Afshin160
شنبه 28 فروردین 1389, 14:48 عصر
با سلام خدمت آقاي موسوي
مثل اينكه من همش بايد مزاحم شما بشم . يكسري اطلاعات بدست آوردم و متوجه شدم فايل هاي wave من از نوع PCM است . و همه آنها هم هدر هاي يكساني يا حجم ديتا مختلف دارند و لي مووضع اينكه اصلا" متوجه نميشم كه چطور بايد فايل را بيت به بيت بخونم و اصلا" چطور يه فايل wave جديد درست كنم .


WAVE PCM soundfile format




The WAVE file format is a subset of Microsoft's RIFF specification for the storage of multimedia files. A RIFF file starts out with a file header followed by a sequence of data chunks. A WAVE file is often just a RIFF file with a single "WAVE" chunk which consists of two sub-chunks -- a "fmt " chunk specifying the data format and a "data" chunk containing the actual sample data. Call this form the "Canonical form". Who knows how it really all works.

I use the standard WAVE format as created by the sox (http://www.spies.com/Sox/) program:


http://i628.photobucket.com/albums/uu4/afshin160/error/110.jpg



Offset Size Name Description

The canonical WAVE format starts with the RIFF header:

0 4 ChunkID Contains the letters "RIFF" in ASCII form

(0x52494646 big-endian form).

4 4 ChunkSize 36 + SubChunk2Size, or more precisely:

4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)

This is the size of the rest of the chunk

following this number. This is the size of the

entire file in bytes minus 8 bytes for the

two fields not included in this count:

ChunkID and ChunkSize.

8 4 Format Contains the letters "WAVE"

(0x57415645 big-endian form).

The "WAVE" format consists of two subchunks: "fmt " and "data":

The "fmt " subchunk describes the sound data's format:

12 4 Subchunk1ID Contains the letters "fmt "

(0x666d7420 big-endian form).

16 4 Subchunk1Size 16 for PCM. This is the size of the

rest of the Subchunk which follows this number.

20 2 AudioFormat PCM = 1 (i.e. Linear quantization)

Values other than 1 indicate some

form of compression.

22 2 NumChannels Mono = 1, Stereo = 2, etc.

24 4 SampleRate 8000, 44100, etc.

28 4 ByteRate == SampleRate * NumChannels * BitsPerSample/8

32 2 BlockAlign == NumChannels * BitsPerSample/8

The number of bytes for one sample including

all channels. I wonder what happens when

this number isn't an integer?

34 2 BitsPerSample 8 bits = 8, 16 bits = 16, etc.

2 ExtraParamSize if PCM, then doesn't exist

X ExtraParams space for extra parameters

The "data" subchunk contains the size of the data and the actual sound:

36 4 Subchunk2ID Contains the letters "data"

(0x64617461 big-endian form).

40 4 Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8

This is the number of bytes in the data.

You can also think of this as the size

of the read of the subchunk following this

number.

44 * Data The actual sound data.

As an example, here are the opening 72 bytes of a WAVE file with bytes shown as hexadecimal numbers:

52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00

22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00

24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d

Here is the interpretation of these bytes as a WAVE soundfile:

http://i628.photobucket.com/albums/uu4/afshin160/error/111.jpg


Notes:


The default byte ordering assumed for WAVE data files is little-endian. Files written using the big-endian byte ordering scheme have the identifier RIFX instead of RIFF.
The sample data must end on an even byte boundary. Whatever that means.
8-bit samples are stored as unsigned bytes, ranging from 0 to 255. 16-bit samples are stored as 2's-complement signed integers, ranging from -32768 to 32767.
There may be additional subchunks in a Wave data stream. If so, each will have a char[4] SubChunkID, and unsigned long SubChunkSize, and SubChunkSize amount of data.
RIFF stands for Resource Interchange File Format.


General discussion of RIFF files:

Multimedia applications require the storage and management of a wide variety of data, including bitmaps, audio data, video data, and peripheral device control information. RIFF provides a way to store all these varied types of data. The type of data a RIFF file contains is indicated by the file extension. Examples of data that may be stored in RIFF files are:


Audio/visual interleaved data (.AVI)
Waveform data (.WAV)
Bitmapped data (.RDI)
MIDI information (.RMI)
Color palette (.PAL)
Multimedia movie (.RMN)
Animated cursor (.ANI)
A bundle of other RIFF files (.BND)


NOTE: At this point, AVI files are the only type of RIFF files that have been fully implemented using the current RIFF specification. Although WAV files have been implemented, these files are very simple, and their developers typically use an older specification in constructing them.

For more info see http://www.ora.com/centers/gff/formats/micriff/index.htm (http://www.ora.com/centers/gff/formats/micriff/index.htm)

References:


http://netghost.narod.ru/gff/graphics/summary/micriff.htm (http://netghost.narod.ru/gff/graphics/summary/micriff.htm) RIFF Format Reference (good).
http://www.lightlink.com/tjweber/StripWav/WAVE.html (http://www.lightlink.com/tjweber/StripWav/WAVE.html)


craig@ccrma.stanford.edu

(Updated by Scott Wilson Jan 20, 2003)



وهمچنين :

Writing to a WAV File

WAV files are in the Resource Interchange File Format (RIFF), which consists of a variable number of named chunks containing either header information (for example, the format of sound samples) or data (the samples themselves). The Win32 API supplies functions for opening and closing RIFF files, seeking to chunks, and so on. The names of these functions all start with "mmio".

The DirectSound API does not include methods for writing to WAV files. However, the DXUTsound.cpp file implements a CWaveFile class that has the following methods for managing capture files:


Open. Opens a file and writes the header chunks.
Write. Writes from a buffer to the data chunk and advances the write cursor.
Close. Writes the size of the data chunk in the header and closes the file.


The first step in writing a WAV file is to call the CWaveFile::Open method. This creates the file and writes the WAV format chunk. The parameters are the filename, a pointer to an initialized WAVEFORMATEX structure, and the WAVEFILE_WRITE flag. The method returns an HRESULT.

The following code opens a WAV file for writing:

CWaveFile g_pWaveFile;

WAVEFORMATEX wfxInput;

ZeroMemory( &wfxInput, sizeof(wfxInput));

wfxInput.wFormatTag = WAVE_FORMAT_PCM;

wfxInput.nSamplesPerSec = 22050

wfxInput.wBitsPerSample = 8;

wfxInput.nChannels = 1;

wfxInput.nBlockAlign =

wfxInput.nChannels * (wfxInput.wBitsPerSample / 8);

wfxInput.nAvgBytesPerSec =

wfxInput.nBlockAlign * wfxInput.nSamplesPerSec;

g_pWaveFile = new CWaveFile;

if (FAILED(g_pWaveFile->Open("mywave.wav", &wfxInput,

WAVEFILE_WRITE)))

{

g_pWaveFile->Close();

}

The application can now begin copying data from the capture buffer to the file.

The following example function is called each time the read cursor reaches a notification position. In this function, the following global variables are used:


g_pDSBCapture is a pointer to the IDirectSoundCaptureBuffer8 (http://msdn.microsoft.com/en-us/library/ee418162%28v=VS.85%29.aspx) interface of the capture buffer.
g_dwNextCaptureOffset tracks the buffer offset of the next block of data that will be copied to the file.
g_dwCaptureBufferSize is the size of the capture buffer, used in calculating wraparound.


HRESULT RecordCapturedData()

{

HRESULT hr;

VOID* pbCaptureData = NULL;

DWORD dwCaptureLength;

VOID* pbCaptureData2 = NULL;

DWORD dwCaptureLength2;

VOID* pbPlayData = NULL;

UINT dwDataWrote;

DWORD dwReadPos;

LONG lLockSize;

if (NULL == g_pDSBCapture)

return S_FALSE;

if (NULL == g_pWaveFile)

return S_FALSE;

if (FAILED (hr = g_pDSBCapture->GetCurrentPosition(

NULL, &dwReadPos)))

return hr;

// Lock everything between the private cursor

// and the read cursor, allowing for wraparound.

lLockSize = dwReadPos - g_dwNextCaptureOffset;

if( lLockSize < 0 ) lLockSize += g_dwCaptureBufferSize;

if( lLockSize == 0 ) return S_FALSE;

if (FAILED(hr = g_pDSBCapture->Lock(

g_dwNextCaptureOffset, lLockSize,

&pbCaptureData, &dwCaptureLength,

&pbCaptureData2, &dwCaptureLength2, 0L)))

return hr;

// Write the data. This is done in two steps

// to account for wraparound.

if (FAILED( hr = g_pWaveFile->Write( dwCaptureLength,

(BYTE*)pbCaptureData, &dwDataWrote)))

return hr;

if (pbCaptureData2 != NULL)

{

if (FAILED(hr = g_pWaveFile->Write(

dwCaptureLength2, (BYTE*)pbCaptureData2,

&dwDataWrote)))

return hr;

}

// Unlock the capture buffer.

g_pDSBCapture->Unlock( pbCaptureData, dwCaptureLength,

pbCaptureData2, dwCaptureLength2 );

// Move the capture offset forward.

g_dwNextCaptureOffset += dwCaptureLength;

g_dwNextCaptureOffset %= g_dwCaptureBufferSize;

g_dwNextCaptureOffset += dwCaptureLength2;

g_dwNextCaptureOffset %= g_dwCaptureBufferSize;

return S_OK;

}

When capturing is finished, the application closes the WAV file.

g_pWaveFile->Close();

ولي اصلا" متوجه نشدم بايد از كجا شروع كنم و چطور بيت به بيت فايلها را بخونم و چطور بهش مقدار بدهم ؟

متشكرم

mehdi.mousavi
شنبه 28 فروردین 1389, 16:09 عصر
سلام.
برای شروع، به همون لینک اول مراجعه کنید که ساختار فایلهای RIFF رو توضیح داده. بعدش، یک Hex Editor روی سیستم نصب کنید، و یک فایل WAV رو بر اساس مطالب اون Document آنالیز کنید. فرضا، مطمئن بشید که 4 بایت اول فایل (CHUNK ID) حتما RIFF هستش. سپس Chunk Size رو بررسی کنید و خلاصه یکی دو روز، فقط روی این مساله کار کنید تا کاملا متوجه ساختار Chunk ها تو RIFF بشید. این Document (http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html) هم میتونه بهتون کمک کنه...

وقتی کاملا به این مساله مسلط شدید، اونوقت دیگه نوشتن کد کاری نداره. کدهایی که الان گذاشتید، یکیش داره از DirectSound برای Capture کردن صدا استفاده میکنه و دیگری کلاس Custom ای رو new میکنه و ... برای استفاده از DirectSound باید به COM مسلط باشید. COM هم چیزی نیستش که بخواهید ظرف مدت کوتاهی بهش غلبه پیدا کنید. ضمن اینکه اگر منظور از DXUT همون DirectX Utility Library باشه، بازهم همون کلاس اول به COM و استفاده از DirectX ختم خواهد شد که در این حالت، دیگه اصلا نیازی به دونستن ساختار فایلها نیست.

ببینید، شما دو روش دارید. یا از DirectShow استفاده کنید که بتونید با گذاشتن چند تا فیلتر به Filter Graph مناسب برای Merge کردن فایلهای مورد نظرتون برسید که میتونید بکمک DirectShow (که بخشی از DirectX هستش) اینکارو انجام بدید، یا از ساختار فایل سر در بیارید و خودتون اینکارو دستی انجام بدید.

اینطور که من متوجه شدم، شما روش دوم رو انتخاب کردید، بنابراین دیگه نباید سراغ DX و استفاده از COM و مسائل مربوطه برید. تو روش دوم، باید ساختار فایل رو یاد بگیرید. Document اول (در پست خودتون) و Document ای که من تو این پست گذاشتم این ساختار رو بهتون توضیح میده. شما نباید این دو روش رو با هم Mix & Match کنید، چون اصلا ارتباطی به همدیگه پیدا نمیکنن.

موفق باشید.