Save output to disk using FMOD - c++

I am using FMOD to play some sounds and I would like to save the resulting mix to the disk.
I have been trying the system->recordStart(0, sound, true) path, but that saves the microphone input of the device.
In some way, I would like to redirect the speakers output to the disk
Thank you
Marc

To redirect everything that would go to the speakers to disk simply use the function System::setOutput and pass in a value of FMOD_OUTPUTTYPE_WAVWRITER. Make sure you call this function before you call System::init, when you are done call System::release and a wav file will appear next to your executable.
You can also specify the name and location of the output wav file by passing a full path via the System::init extradriverdata parameter.

Related

Determining the format of audio file (MP3) using SAPI

HiI'm trying to create a "Speech to text" app that can transcribe any audio/video file. I've created an app based on this post and it works great for WAV files. But if I use an MP3 file, the line hr = cpInputStream->BindToFile(wInputFileName.c_str(), SPFM_OPEN_READONLY, &sInputFormat.FormatId(), sInputFormat.WaveFormatExPtr(), SPFEI_ALL_EVENTS); returns
The Parameter is incorrect
The question is, can I use MP3 files as input for SAPI? and if yes, how do I determine the correct format for the call to hr = sInputFormat.AssignFormat(SPSF_16kHz16BitStereo) because SPSF_16kHz16BitStereo will certainly not be correct and I don't think we should hardcode it.

Recovering Files on Windows and C

Well this time I'm trying to write a program in C which recover deleted files from a disk, it could be an external disk, I have an idea than i had used before on linux, it is to open the disk as a kind of file and scaning the Headers and file footers of everything within the disk, the point is I'm not sure if there's allow on windows to open a disk as an File, basiclly I have the logic how to develope this program, but I'm not sure how to implement it on windows, anybody can give me a hand with this?.
The code I used on linux to open a disk as a file was:
Edit: That was a sample of what I was using guys, it's just to give you an idea of what I was doing, the correct syntax I used was the next:
direccion = ui->linea->text().toLatin1().constData();
f = fopen(direccion,"rb");
I used QT creator on linux, and direccion variable was a TextField value which contained the file path of the disk through a button function that open a QFileDialog...
could I use it in windows as well?
Thank you before hand..
"The code I used on linux to open a disk as a file was:"
File *f = fopen("E:\", "rb");
I seriously doubt you ever got this code working on any linux system (or windows either).
You'll need to escape the backslash path delimiter, if it's presented in any string literal:
FILE* f = fopen("E:\\", "rb");
// ^
Also all that filesystem path style you are presenting to access a particular disk, is about accessing a windows file path/disk.
No linux file system has notion about drive characters, and the file path delimiter value used is '/', not '\\'.
To recover deleted files, you can't use fopen or fstream::open because the file was deleted. Check the return value from the function or test the stream state.
The way to recover deleted files is:
Get the Master File Table as raw data.
Search for the record containing a string similar to the deleted
filename.
Change the entry in the Master File Table to "undeleted".
Write the Master File Table back to the drive.
The above usually requires platform specific API, which is different on Linux and Windows platforms.

WriteFileGather - append buffers to file

Using Windows API's WriteFileGather, I am writing a file to the disk.
I want to append new buffers to the existing file.
What is the way to prevent WriteFileGather from overwriting the existing file?
WriteFileGather will never overwrite the file unless you ask it to - theres no implied overwrite/append option, theres ONLY a 'please write data at file position X option'.
You should open the file handle normally (making sure you've got GENERIC_WRITE access and specifying flags at least flags FILE_FLAG_OVERLAPPED and FILE_FLAG_NO_BUFFERING by using CreateFile
Then you set the position the file writes at by using the Offset and OffsetHigh members of the OVERLAPPED you pass in as the 5th parameter.
This is similar to the way WriteFile works when its running in asynchronous mode - you must specify the position to write at. Its probably easier to learn how to do positional asyncronous writes using WriteFile first then move onto WriteFileGather if you need its additional power.
See here for docs.
EDIT: To answer the comment from Harry, to get the end of file you can either remember how much you've written before (assuming this is a new file you created) or get the current file size from a HANDLE using SetFilePointerEx with distance 0 and method FILE_END which will return to you the end of the file. There are other ways of getting a file size but beware you may get a cached answer (e.g. if iterating over a directory) and so the above is recommended.

Mini-Filter intercept drag & drop file(s) to disk?

I am developing a mini-filter to intercept files and get the name of files which are dragged & dropped to a specific disk and get the file names.
If I drag & drop a file, I can get this file name and intercept it successfully (That's mean this file is not created on disk).
If I drag & drop multiple files, I can only get the first file name and other is not. But when I open the disk, I don't see any file here (That's mean Mini-Filter intercept them successfully). So I can not get the file names (except the first file)
I intercept drag & drop by redirect them:
Get file name by FltGetFileNameInformation() then FltParseFileNameInformation()
Split it two part
First is: \Device\HarddiskVolume1\folder\
Second is: file.ext
Append a file name for first part: \Device\HarddiskVolume1\folder\new_file.ext
Intercept create on disk
Release this buffer: Data->Iopb->TargetFileObject->FileName.Buffer
Assign first part to Data->Iopb->TargetFileObject->FileName
Set this: Data->Iopb->TargetFileObject->RelatedFileObject = NULL;
Data->IoStatus.Information = IO_REPARSE;
Data->IoStatus.Status = STATUS_REPARSE;
return FLT_PREOP_SUCCESS_NO_CALLBACK;
Above code can only intercept all files and get the first file name.
How can I do to intercept each file when I drag & drop multiple file?
I found myself that:
Get file name from Data->Iopb->TargetFileObject->FileName
Slipt it two part: file path and file name
Change file name to a redirect file name
Delete redirect file name. This step can be run before step #1
If redirect file name is not exist, It return STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034). It is not problem for system.
If redirect file name is exist. It is OK.
Make sure you check the simrep sample from Microsoft they show you how to properly do this.
I would not base my assumption that Drag&Drop has a correspondence in the kernel and in the file-system. It can be implemented in user-mode in many ways especially if you are doing it on the same volume. It can be as simple as a rename. Also keep in mind hard-links and symboliclinks and alternate data streams.
Good luck.

Edit the frame rate of an avi file

Is it possible to change the frame rate of an avi file using the Video for windows library? I tried the following steps but did not succeed.
AviFileInit
AviFileOpen(OF_READWRITE)
pavi1 = AviFileGetStream
avi_info = AviStreamInfo
avi_info.dwrate = 15
EditStreamSetInfo(dwrate) returns -2147467262.
I'm pretty sure the AVIFile* APIs don't support this. (Disclaimer: I was the one who defined those APIs, but it was over 15 years ago...)
You can't just call EditStreamSetInfo on an plain AVIStream, only one returned from CreateEditableStream.
You could use AVISave, then, but that would obviously re-copy the whole file.
So, yes, you would probably want to do this by parsing the AVI file header enough to find the one DWORD you want to change. There are lots of documents on the RIFF and AVI file formats out there, such as http://www.opennet.ru/docs/formats/avi.txt.
I don't know anything about VfW, but you could always try hex-editing the file. The framerate is probably a field somewhere in the header of the AVI file.
Otherwise, you can script some tool like mencoder[1] to copy the stream to a new file under a different framerate.
[1] http://www.mplayerhq.hu/
HRESULT: 0x80004002 (2147500034)
Name: E_NOINTERFACE
Description: The requested COM interface is not available
Severity code: Failed
Facility Code: FACILITY_NULL (0)
Error Code: 0x4002 (16386)
Does it work if you DON'T call EditStreamSetInfo?
Can you post up the code you use to set the stream info?