How to insert one wav audio file into antoher wav file? - c#

I am working on xamarin. And I have developed an app in which I record voice of user. Now I want that user can insert again in his already recorded file. I mean if a user has alrady recorded for 10 min and now he want to insert some more content at 6 min, he should be able to do that. I tried some examples but not getting success. When I am inserting some times its working and sometimes the inserted content get corrupt after insertion.
Following is my code that I have implemente. It is working for some time and some time inserted content get corrupt.
string[] files = new string[] { originalFile, insertFile };
if (!files[0].Contains("tempfile_") && files.Length > 1)
{
if (File.Exists(files[0]))
{
string newPath = files[1].Replace("tempfile_1",
"tempfile_0");
MoveExistingFile(files[0], newPath);
files[0] = newPath;
}
else
{
files = files.Skip(1).ToArray();
}
}
var duration = DependencyService.Get<IPlayService>
().GetDuration(files[0]);
var bufferTime = Math.Round(duration);
FileStream originalStream = new FileStream(files[0],
FileMode.Open, FileAccess.Read);
byte[] originalByteArray = new byte[originalStream.Length - 44];
var perSecondLength = originalByteArray.Length / (int)bufferTime;
var splitIndex = (perSecondLength * SplitSecond);
var byteArray1 = new byte[(splitIndex)];
var byteArray2 = new byte[originalByteArray.Length - splitIndex];
FileStream insertStream = new FileStream(files[1], FileMode.Open,
FileAccess.Read);
byte[] insertByteArray = new byte[insertStream.Length - 44];
var byteArray3 = new byte[insertByteArray.Length];
originalStream.Position = 44;
originalStream.Read(byteArray1, 0, byteArray1.Length);
originalStream.Position = byteArray1.Length;
originalStream.Read(byteArray2, 0, byteArray2.Length);
originalStream.Close();
insertStream.Position = 44;
insertStream.Read(byteArray3, 0, byteArray3.Length);
insertStream.Close();
WaveIO wa_IN = new WaveIO();
WaveIO wa_out = new WaveIO();
wa_out.DataLength = 0;
wa_out.length = 0;
//Gather header data
foreach (string path in files)
{
wa_IN.WaveHeaderIN(#path);
wa_out.DataLength += wa_IN.DataLength;
wa_out.length += wa_IN.length;
}
//Recontruct new header
wa_out.BitsPerSample = wa_IN.BitsPerSample;
wa_out.channels = wa_IN.channels;
wa_out.samplerate = wa_IN.samplerate;
wa_out.WaveHeaderOUT(#outfile);
FileStream fo = new FileStream(#outfile, FileMode.Append,
FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fo);
bw.Write(byteArray1);
bw.Write(byteArray3);
bw.Write(byteArray2);
bw.Close();
fo.Close();

Related

c# openxml set up self running power point presentation

I am working on one demo application (Asp.net MVC) where i want to apply self running and transition time animation on existing Power Points. I wrote below code,
using (var templateFile = System.IO.File.Open(Server.MapPath("~/OurCompanyTeam.pptx"), FileMode.Open, FileAccess.Read))
{
using (var stream = new MemoryStream())
{
templateFile.CopyTo(stream);
using (var presentationDocument = PresentationDocument.Open(stream, true))
{
var presentationPart = presentationDocument.PresentationPart;
var presentation = presentationPart.Presentation;
var slideList = new List<SlidePart>();
foreach (SlideId slideID in presentation.SlideIdList)
{
var slide = (SlidePart)presentationPart.GetPartById(slideID.RelationshipId);
Transition trns = new Transition();
trns.Duration = "2.5";
trns.Speed = TransitionSpeedValues.Fast;
slide.Slide.Transition = trns;
slideList.Add(slide);
}
presentationPart.Presentation.Save();
}
byte[] buffer = stream.ToArray();
MemoryStream ms = new MemoryStream(buffer);
FileStream file = new FileStream(Server.MapPath("~/output.pptx"), FileMode.Create, FileAccess.Write);
ms.WriteTo(file);
file.Close();
}
}
How could i improve this code to set up self running presentation?
The code in this answer will make any presentation(.pptx) a self running Slide Show (.ppsx). It does the following items:
Puts the presentation in kiosk mode
Sets the AdvanceAfterTime attribute to 2 seconds for each slide
Change the Document type to Slide Show
Saves contents of .pptx to a new .ppsx file.
You can replace your code above with the following code. Add a _sourceFile string local variable to save the full path to your file. Notes in the comments for the items above:
using (var templateFile = System.IO.File.Open(Server.MapPath("~/OurCompanyTeam.pptx"), FileMode.Open, FileAccess.Read))
{
using (var stream = new MemoryStream())
{
templateFile.CopyTo(stream);
using (var presentationDocument = PresentationDocument.Open(stream, true))
{
var presentationPart = presentationDocument.PresentationPart;
var presentation = presentationPart.Presentation;
var slideList = new List<SlidePart>();
foreach (SlideId slideID in presentation.SlideIdList)
{
var slidePart = (SlidePart)presentationPart.GetPartById(slideID.RelationshipId);
AlternateContent alternateContent1 = slidePart.Slide.GetFirstChild<AlternateContent>();
if (alternateContent1 != null)
{
slidePart.Slide.RemoveAllChildren<AlternateContent>();
}
var trns1 = new Transition();
trns1.Duration = "2000";
trns1.AdvanceOnClick = false;
trns1.AdvanceAfterTime = "2000"; //ITEM #2
trns1.Speed = TransitionSpeedValues.Slow;
var alternateContent = new AlternateContent();
alternateContent.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
AlternateContentChoice alternateContentChoice = new AlternateContentChoice() { Requires = "p14" };
alternateContentChoice.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
alternateContentChoice.Append(trns1);
alternateContent.Append(alternateContentChoice);
slidePart.Slide.Append(alternateContent);
}
var presentationPropertiesPart = presentationPart.PresentationPropertiesPart;
var presentationProperties = presentationPropertiesPart.PresentationProperties;
presentationProperties.RemoveAllChildren<ShowProperties>();
presentationProperties.Append(NewShowProperties());
presentationDocument.ChangeDocumentType(PresentationDocumentType.Slideshow); //ITEM #3
}
byte[] buffer = stream.ToArray();
MemoryStream ms = new MemoryStream(buffer);
FileStream file = new FileStream(System.IO.Path.GetDirectoryName(_sourceFile) + "/NewSlideShow.ppsx",
FileMode.Create, FileAccess.Write); //ITEM #4
ms.WriteTo(file);
file.Close();
}
}
then add this method at the bottom of your class:
private ShowProperties NewShowProperties()
{
var showProperties = new ShowProperties { Loop = true, ShowNarration = true };
showProperties.Append(new KioskSlideMode()); //ITEM #1
showProperties.Append(new SlideAll());
showProperties.Append(new PresenterSlideMode());
return showProperties;
}
I've tested this to work on newly created PowerPoint 2013 and 2016 Presentations. Double click on the .ppsx file and it will launch the self-running presentation.

How to generate a zip with a dat file and a txt file with C#

I need to create a file txt and a file with extension dat. After that I want to compress these files into a zip file and to download it.
My problem is that I don't want to save the files before download. So, can I create and download the zip without creating files on server?
I used MemoryStream. Below you can find the code:
public ZipOutputStream CreateZip(MemoryStream memoryStreamControlFile, MemoryStream memoryStreamDataFile)
{
using (var outputMemStream = new MemoryStream())
{
using (var zipStream = new ZipOutputStream(baseOutputStream))
{
zipStream.SetLevel(3); // 0-9, 9 being the highest level of compression
byte[] bytes = null;
// .dat
var nameFileData = CreateFileName("dat");
var newEntry = new ZipEntry(nameFileData) { DateTime = DateTime.Now };
zipStream.PutNextEntry(newEntry);
bytes = memoryStreamDataFile.ToArray();
var inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
// .suc
var nameFileControl = CreateFileName("suc");
newEntry = new ZipEntry(nameFileControl) { DateTime = DateTime.Now };
zipStream.PutNextEntry(newEntry);
bytes = memoryStreamControlFile.ToArray();
inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
// .zip
zipStream.IsStreamOwner = false;
zipStream.Close();
outputMemStream.Position = 0;
return zipStream;
}
}
}
I assume you are working with ASP.Net ?
You can put the file contents (stream, etc...) in a byte array, then output that directly to the user in the response, like :
string fileType = "...zip...";
byte[] fileContent = <your file content> as byte[];
int fileSize = 1000;
string fileName = "filename.zip";
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
Response.ContentType = fileType;
Response.OutputStream.Write(fileContent, 0, fileSize);

Creating zip file of multiple byte[] arrays / files

I am trying to create a zip file that contains zip files inside of it. I am using ICSharpCode.SharpZipLib (must use this due to project restrictions). this works fine if I have only 1 byte[] array.. but it is not working for list of byte[].
foreach (byte[] internalZipFile in zipFiles)
{
// Source : internal zip file
MemoryStream inputMemoryStream = new MemoryStream(internalZipFile);
ZipEntry newZipEntry = new ZipEntry("AdManifest-" + i.ToString() + ".zip");
newZipEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newZipEntry);
StreamUtils.Copy(inputMemoryStream, zipStream, new byte[1024]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // to stop the close and underlying stream
zipStream.Close();
outputMemoryStream.Position = 0;
zipByteArray = outputMemoryStream.ToArray();
i++;
}
using (FileStream fileStream = new FileStream(#"c:\manifest.zip", FileMode.Create))
{
fileStream.Write(zipByteArray, 0, zipByteArray.Length);
}
Can someone please assist? what am i missing?
I figured this out.
here us the one working for me :
byte[] zipByteArray = null;
int i = 0;
if (zipFiles != null && zipFiles.Count > 0)
{
MemoryStream outputMemoryStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemoryStream);
zipStream.SetLevel(3);
foreach (byte[] internalZipFile in zipFiles)
{
MemoryStream inputMemoryStream = new MemoryStream(internalZipFile);
ZipEntry newZipEntry = new ZipEntry("AdManifest-" + i.ToString() + ".zip");
newZipEntry.DateTime = DateTime.Now;
newZipEntry.Size = internalZipFile.Length;
zipStream.PutNextEntry(newZipEntry);
StreamUtils.Copy(inputMemoryStream, zipStream, new byte[1024]);
zipStream.CloseEntry();
i++;
}
zipStream.IsStreamOwner = false; // to stop the close and underlying stream
zipStream.Close();
outputMemoryStream.Position = 0;
zipByteArray = outputMemoryStream.ToArray();
using (FileStream fileStream = new FileStream(#"c:\manifest.zip", FileMode.Create))
{
fileStream.Write(zipByteArray, 0, zipByteArray.Length);
}
}
I can't try it, but i think than you need less code in iteration body
Plus that i've removed outpustmemorystream and used only zipStream.
foreach (byte[] internalZipFile in zipFiles)
{
// Source : internal zip file
MemoryStream inputMemoryStream = new MemoryStream(internalZipFile);
ZipEntry newZipEntry = new ZipEntry("AdManifest-" + i.ToString() + ".zip");
newZipEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newZipEntry);
StreamUtils.Copy(inputMemoryStream, zipStream, new byte[1024]);
zipStream.CloseEntry();
i++;
}
zipStream.IsStreamOwner = false; // to stop the close and underlying stream
zipStream.Position = 0;
zipByteArray = zipStream.ToArray();
zipStream.Close();
using (FileStream fileStream = new FileStream(#"c:\manifest.zip", FileMode.Create))
{
fileStream.Write(zipByteArray, 0, zipByteArray.Length);
}

C# ZipArchive losing data

I'm trying to copy the contents of one Excel file to another Excel file while replacing a string inside of the file on the copy. It's working for the most part, but the file is losing 27 kb of data. Any suggestions?
public void ReplaceString(string what, string with, string path) {
List < string > doneContents = new List < string > ();
List < string > doneNames = new List < string > ();
using(ZipArchive archive = ZipFile.Open(_path, ZipArchiveMode.Read)) {
int count = archive.Entries.Count;
for (int i = 0; i < count; i++) {
ZipArchiveEntry entry = archive.Entries[i];
using(var entryStream = entry.Open())
using(StreamReader reader = new StreamReader(entryStream)) {
string txt = reader.ReadToEnd();
if (txt.Contains(what)) {
txt = txt.Replace(what, with);
}
doneContents.Add(txt);
string name = entry.FullName;
doneNames.Add(name);
}
}
}
using(MemoryStream zipStream = new MemoryStream()) {
using(ZipArchive newArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true, Encoding.UTF8)) {
for (int i = 0; i < doneContents.Count; i++) {
int spot = i;
ZipArchiveEntry entry = newArchive.CreateEntry(doneNames[spot]);
using(var entryStream = entry.Open())
using(var sw = new StreamWriter(entryStream)) {
sw.Write(doneContents[spot]);
}
}
}
using(var fileStream = new FileStream(path, FileMode.Create)) {
zipStream.Seek(0, SeekOrigin.Begin);
zipStream.CopyTo(fileStream);
}
}
}
I've used Microsoft's DocumentFormat.OpenXML and Excel Interop, however, they are both lacking in a few main components that I need.
Update:
using(var fileStream = new FileStream(path, FileMode.Create)) {
var wrapper = new StreamWriter(fileStream);
wrapper.AutoFlush = true;
zipStream.Seek(0, SeekOrigin.Begin);
zipStream.CopyTo(wrapper.BaseStream);
wrapper.Flush();
wrapper.Close();
}
Try the process without changing the string and see if the file size is the same. If so then it would seem that your copy is working correctly, however as Marc B suggested, with compression, even a small change can result in a larger change in the overall size.

Looking for workaround due to FileStream.Create UnauthorizedAccessException

I am using FileStream.Create to upload a .csv file onto a server and then read it into a SQL database. Once it is read in, I just delete the file from the folder that it was written to. The goal is to just get the file into the database. This would run fine locally, but I cannot get write access on the new server so I get an UnauthorizedAccessException. I don't think that it is necessary to upload the file to the server to read it into the SQL table, but I am having trouble adjusting the code.
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
var cc = new CsvContext();
var filePath = uploadFile(csvFile.InputStream);
var model = cc.Read<Credit>(filePath, inputFileDescription);
try
{
var entity = new Entities();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
Id = item.Id,
Amount = item.Amount,
Date = item.Date,
Number = item.Number,
ReasonId = item.ReasonId,
Notes = item.Notes
};
entity.TemporaryCsvUploads.Add(tc);
}
entity.SaveChanges();
System.IO.File.Delete(filePath);
Here is the uploadFile method:
private string uploadFile(Stream serverFileStream)
{
const string directory = "~/Content/CSVUploads";
var directoryExists = Directory.Exists(Server.MapPath(directory));
if (!directoryExists)
{
Directory.CreateDirectory(Server.MapPath(directory));
}
var targetFolder = Server.MapPath(directory);
var filename = Path.Combine(targetFolder, Guid.NewGuid() + ".csv");
try
{
const int length = 256;
var buffer = new byte[length];
// write the required bytes
using (var fs = new FileStream(filename, FileMode.Create))
{
int bytesRead;
do
{
bytesRead = serverFileStream.Read(buffer, 0, length);
fs.Write(buffer, 0, bytesRead);
} while (bytesRead == length);
}
serverFileStream.Dispose();
return filename;
}
catch (Exception)
{
return string.Empty;
}
}
To sum it up, I am uploading a .csv file to a temporary location, reading it into an object, reading it into a database, then deleting the .csv file out of the temporary location. I am using Linq2Csv to create the object. Can I do this without uploading the file to the server (because I can't get write access)?
According to http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library,
you can read from a StreamReader
Read<T>(StreamReader stream)
Read<T>(StreamReader stream, CsvFileDescription fileDescription)
You can probably use a streamreader (or a stringbuilder) to create your file instead of a csv - Write StringBuilder to Stream
How to take a stringbuilder and convert it to a streamReader?
and then send that to your CSVContext?

Categories

Resources