UWP Windows 10 IoT 2 channel Simultaneous Audio Recording - c#

I would like to know how to record 2 separate audio channel simultaneously.
I have 2 USB adapters with mic & speaker respectively.
The samples code which I can find only support single channel recording at a time.
Please help. Thanks.
For single channel my code as follow;
MediaCapture audioCapture = new MediaCapture();
MediaCaptureInitializationSettings captureInitSettings = new MediaCaptureInitializationSettings();
captureInitSettings.StreamingCaptureMode = StreamingCaptureMode.Audio;
captureInitSettings.MediaCategory = MediaCategory.Other;
captureInitSettings.AudioProcessing = AudioProcessing.Default;
await audioCapture.InitializeAsync(captureInitSettings);
private async void recordChannelA()
{
StorageFolder externalDevices = KnownFolders.RemovableDevices;
IReadOnlyList<StorageFolder> externalDrives = await externalDevices.GetFoldersAsync();
StorageFolder usbStorage = externalDrives[0];
if (usbStorage != null)
{
StorageFolder recordFolder = await usbStorage.CreateFolderAsync(recFolderName, CreationCollisionOption.OpenIfExists);
await usbStorage.GetFolderAsync(recFolderName);
StorageFile recordFile = await recordFolder.CreateFileAsync("Recording - " + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".mp3", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
MediaEncodingProfile profile = null;
profile = MediaEncodingProfile.CreateM4a(Windows.Media.MediaProperties.AudioEncodingQuality.Auto);
await audioCapture.StartRecordToStorageFileAsync(profile, recordFile);
Message.Text = "Recording ... ";
recordingtimerRun = new TimeSpan(0, 0, 0);
recordingTimer.Start();
}
else Message.Text = "Recording error !";
}
Update;
I created a 'listview' for the enumerated devices and to select the respective capture device. However, there is an Syntax Error which i cannot convert the enumaration.deviceinformation to imediasource.
captureInitSettings.AudioSource = captureDeviceList[audioCaptureList.SelectedIndex];
Update: I managed to get it to work
The solution is
captureInitSettingsA.AudioDeviceId = captureDeviceList[audioCaptureList.SelectedIndex].Id;
captureInitSettingsB.AudioDeviceId = captureDeviceList[audioCaptureList.SelectedIndex].Id;
However, how do i save these selections in app settings .. so that when I reboot I don't have to re-select again.
Update:
I manage to save the app setting for audiocapture & audiorender devices but I am not sure how to retrieve them & also to check if there is any previous settings saved.
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
localSettings.Values["audioACaptureSettings"] = captureAInitSettings.AudioDeviceId;
localSettings.Values["audioARenderSettings"] = mediaPlayerA.AudioDevice.Id;
localSettings.Values["audioBCaptureSettings"] = captureBInitSettings.AudioDeviceId;
localSettings.Values["audioBRenderSettings"] = mediaPlayerB.AudioDevice.Id;
private void loadAudioConfig()
{
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
if (localSettings.Values["audioACaptureSettings"] != null)
{
captureAInitSettings.AudioDeviceId = localSettings.Values["audioACaptureSettings"].ToString();
}
if (localSettings.Values["audioARenderSettings"] != null)
{
Object audioARenderValue = localSettings.Values["audioARenderSettings"];
mediaPlayerA.AudioDevice = audioARenderValue;
}
if (localSettings.Values["PAaudioCaptureSettings"] != null)
{
captureBInitSettings.AudioDeviceId = localSettings.Values["audioBCaptureSettings"].ToString();
}
if (localSettings.Values["PAaudioRenderSettings"] != null)
{
Object audioBRenderValue = localSettings.Values["audioBRenderSettings"];
mediaPlayerB.AudioDevice = audioBRenderValue;
}

You can refer to this document which introduced how to store and retrieve settings and other app data. You can save the data to Settings and Files.
When you use Settings, it only supports multiple data types as mentioned in the document.
If use files, you can store binary data or to enable your own, customized serialized types,.
In your provided code, it is correct to check if there is any previous settings saved:
if (localSettings.Values["audioACaptureSettings"] != null)
{
captureAInitSettings.AudioDeviceId = localSettings.Values["audioACaptureSettings"].ToString();
}
But it is incorrect about how to retrieve the setting as AudioDevice because it can not implicitly convert string to DeviceInformation. Please try in this way:
if (localSettings.Values["audioARenderSettings"] != null)
{
var aduioSource = localSettings.Values["audioARenderSettings"] as string;
mediaPlayerA.AudioDevice = await DeviceInformation.CreateFromIdAsync(aduioSource);
}

Related

Setting MediaStreamProperties on HoloLens does not work

I am working on an UWP app for the HoloLens to read single frames from the devices camera. I want to use the camera mode with the lowest resolution available.
I took a look at the following links and examples and tried to create a minimal working app:
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/set-media-encoding-properties
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/use-opencv-with-mediaframereader
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CameraResolution
https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/CameraOpenCV
This is the code snippet from MainPage.xaml.cs:
public async Task<int> Start()
{
// Find the sources
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
var sourceGroups = allGroups.Select(g => new
{
Group = g,
SourceInfo = g.SourceInfos.FirstOrDefault(i => i.SourceKind == MediaFrameSourceKind.Color)
}).Where(g => g.SourceInfo != null).ToList();
if (sourceGroups.Count == 0)
{
// No camera sources found
return 0;
}
var selectedSource = sourceGroups.FirstOrDefault();
// Initialize MediaCapture
_mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings()
{
SourceGroup = selectedSource.Group,
SharingMode = MediaCaptureSharingMode.ExclusiveControl,
StreamingCaptureMode = StreamingCaptureMode.Video,
MemoryPreference = MediaCaptureMemoryPreference.Cpu
};
await _mediaCapture.InitializeAsync(settings);
// Query all properties of the device
IEnumerable<StreamResolution> allVideoProperties = _mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord).Select(x => new StreamResolution(x));
// Order them by resolution then frame rate
allVideoProperties = allVideoProperties.OrderBy(x => x.Height * x.Width).ThenBy(x => x.FrameRate);
await _mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, allVideoProperties.ElementAt(0).EncodingProperties);
// Create the frame reader
MediaFrameSource frameSource = _mediaCapture.FrameSources[selectedSource.SourceInfo.Id];
_reader = await _mediaCapture.CreateFrameReaderAsync(frameSource, MediaEncodingSubtypes.Bgra8);
_reader.FrameArrived += ColorFrameReader_FrameArrivedAsync;
await _reader.StartAsync();
return 1;
}
private async void ColorFrameReader_FrameArrivedAsync(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
var frame = sender.TryAcquireLatestFrame();
if (frame != null)
{
var inputBitmap = frame.VideoMediaFrame?.SoftwareBitmap;
}
}
On my local machine (MacBookPro with Bootcamp partition) this code works using the webcam. It detects three supported video modes. I can change the resolution of the bitmap image in FrameArrivedAsync by changing the index from 0 to 1 or 2 at:
_mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, allVideoProperties.ElementAt(0).EncodingProperties);
On HoloLens this code does not work. It detects the different modes like explained here (https://learn.microsoft.com/en-us/windows/mixed-reality/locatable-camera). But setting the MediaStreamProperties does not change anything regarding the received bitmap image. The bitmap is always 1280x720.
Just in case, we want to share how we setup the capture profile, you can refer to the following code with annotate to modify your project for testing. If in doubt, please feel free to add comments.
private async void SetupAndStartMediaCapture()
{
string deviceId = string.Empty;
_mediaCapture = new MediaCapture();
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
foreach (var device in devices)
{
if(MediaCapture.IsVideoProfileSupported(device.Id))
{
deviceId = device.Id;
break; // The video device for which supported video profile support is queried.
}
}
MediaCaptureInitializationSettings mediaCapSettings = new MediaCaptureInitializationSettings
{
VideoDeviceId = deviceId
};
IReadOnlyList<MediaCaptureVideoProfile> profiles = MediaCapture.FindAllVideoProfiles(deviceId);
var profileMatch = (
from profile in profiles
from desc in profile.SupportedRecordMediaDescription
where desc.Width == 896 && desc.Height == 504 && desc.FrameRate == 24 // HL1
select new { profile, desc }
).FirstOrDefault();// Select the Profile with the required resolution from all available profiles.
if (profileMatch != null)
{
mediaCapSettings.VideoProfile = profileMatch.profile;
mediaCapSettings.RecordMediaDescription = profileMatch.desc;
}
await _mediaCapture.InitializeAsync(mediaCapSettings); //Initializes the MediaCapture object.
}

Winform Cefsharp: Can't clear cache directory

I'm using CefSharp in my WinForm project.
I wan't to clear the cache directory in real time:
if (browser != null)
{
BrowserPanel.Controls.Remove(browser);
browser = null;
}
String cachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\TelegramParser\Users\" + userName;
if (Directory.Exists(cachePath))
{
Directory.Delete(cachePath, true);
}
But I always get an error that it is not possible to delete this directory.
This is how I declare the browser:
String cachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\TelegramParser\Users\" + userName;
if (!System.IO.Directory.Exists(cachePath))
{
System.IO.Directory.CreateDirectory(cachePath);
}
var requestContextSettings = new RequestContextSettings { CachePath = cachePath };
if (browser != null && BrowserPanel.Controls.Contains(browser))
BrowserPanel.Controls.Remove(browser);
browser = new ChromiumWebBrowser();
browser.RequestContext = new RequestContext(requestContextSettings, new CustomRequestContextHandler());
browser.Dock = DockStyle.Fill;
JsDialogHandler js1 = new JsDialogHandler();
browser.JsDialogHandler = js1;
BrowserPanel.Controls.Add(browser);
browser.Load("https://google.com/");
What can I do to fix this?
As of 85.4 it is possible to delete cache of a running CefSharp browser using DevToolsClient and Network.ClearBrowserChache. As mentioned on General Usage wiki of CefSharp.
private async Task ClearCache(object sender)
{
using (var devToolsClient = Browser.GetDevToolsClient())
{
var response = await devToolsClient.Network.ClearBrowserCacheAsync();
}
}
Note: this will not deleted the entire folder, it will however clear cached objects.

Get image download url from firebase storage Xamarin

Im trying to get the image url from a photo I uploaded to firebase storage so I can store the reference to the image in another table which will allow me to be able to display the image elsewhere throughout the app.
I currently have
private void UploadPhoto()
{
if (filePAth != null)
{
progressDialog = new ProgressDialog(this);
progressDialog.SetTitle("Uploading...");
progressDialog.Window.SetType(Android.Views.WindowManagerTypes.SystemAlert);
progressDialog.Show();
var images = storageRef.Child("images/" + Guid.NewGuid().ToString());
images.PutFile(filePAth)
.AddOnProgressListener(this)
.AddOnSuccessListener(this)
.AddOnFailureListener(this);
}
}
public async void OnSuccess(Java.Lang.Object result)
{
try
{
var newImageDetails = storageRef.Child("images" + "/" + filePAth);
Photo photos = new Photo();
photos.categoryName = spinner.SelectedItem.ToString();
photos.photoId = newImageDetails.Name;
photos.ImageUrl = storageRef.DownloadUrl.ToString();
photos.tagName = addTag.Text;
if (user != null)
{
var uid = user.Uid;
//set the users id to the category
photos.uid = uid;
}
var firebase = new FirebaseClient(FirebaseURL);
var item = await firebase.Child("photos").PostAsync(photos);
}
}
The storageref.DownloadUrl does not give me the correct url
This is what I am looking for
I think that the trouble is Guid.NewGuid().
It generates a new code each time you insert a new image and your storageref points to it (image/GUID code).
In your OnSuccess you get image info from "images/" + filePath, that's different from upload path.
Why you use a new GUID? You can't determinate it, it will create a different path each time.
Consider then that your download url contains the media token too, it's not simply the clean path as you expect
I got a solution in debugging mode
i saw the downloadurl's properties and found the Scheme and SchemeSpecificPart
Scheme = "https"
SchemeSpecificPart = "//firebasestorage.googleapis.com/v0/b/maplog-e4ba5.appspot.com/o/-L0AMbihF23YKxsL1uss?alt=media&token=5c7ccef1-c857-4982-a288-fded2f0ff1aa"
so here is my code:
void IOnSuccessListener.OnSuccess(Java.Lang.Object result)
{
var snapShot = (UploadTask.TaskSnapshot)result;
string imgUrl = snapShot.DownloadUrl.Scheme
+ ":"
+ snapShot.DownloadUrl.SchemeSpecificPart;
}
and it works! i was looking for the solution :(( but i finally found it myself XD

TrySetWallpaperImageAsync() always returns false

I'm trying to set the wallpaper to an image on my Windows 10 device:
var fileName = postInf.title + ".jpg";
BitmapImage img = new BitmapImage();
bool success = false;
if (UserProfilePersonalizationSettings.IsSupported())
{
// read from pictures library
var pictureFile = await KnownFolders.PicturesLibrary.GetFileAsync(fileName);
using (var pictureStream = await pictureFile.OpenAsync(FileAccessMode.Read))
{
img.SetSource(pictureStream);
}
UserProfilePersonalizationSettings profileSettings = UserProfilePersonalizationSettings.Current;
success = await profileSettings.TrySetWallpaperImageAsync(pictureFile);
}
return success;
The storagefile is created fine, have tried with various images from various folders (e.g. My Pictures, Assets, LocalState); always returns false and wallpaper is not set? I have read/write permissions to pictures library, have tried running in debug and release versions. Apparently others are also having this problem.
Your app can't set wallpapers from any folder. Copy file in ApplicationData.Current.LocalFolder and set wallpaper from there.
My code:
if (list.SelectedIndex != -1)
{
var data = list.SelectedItem as ThumbItem;
StorageFile newFile = await data.File.CopyAsync(ApplicationData.Current.LocalFolder);
await SetWallpaperAsync(newFile);
}
async Task<bool> SetWallpaperAsync(StorageFile fileItem)
{
bool success = false;
if (UserProfilePersonalizationSettings.IsSupported())
{
UserProfilePersonalizationSettings profileSettings = UserProfilePersonalizationSettings.Current;
success = await profileSettings.TrySetWallpaperImageAsync(fileItem);
}
return success;
}

How to relate between open file picker and storage file?

look for this error and tell me your opinion to solve this problem
I was making window phone Application :
its can't save my picked file in a storage file to trim it as media
or I can not relate between open file picker and storage file if anyone have any ideas how to relate between them or have any demos please tell me
I'm not sure I understood your problem. Here is my code for picking a file and write into it in WinRT/Win10 store app.
private async void SaveFileExecute()
{
var fileNameTab = FileName.Split('.');
var extension = fileNameTab[1];
var fileName = fileNameTab[0];
var savePicker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
SuggestedFileName = fileName
};
savePicker.FileTypeChoices.Add(extension, new List<string> { "." + extension });
var saveFile = await savePicker.PickSaveFileAsync();
if (saveFile != null)
{
using (var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
using (var outputStream = fileStream.GetOutputStreamAt(0))
{
using (var dataWriter = new DataWriter(outputStream))
{
dataWriter.WriteBytes(SelectedFile.Data);
await dataWriter.StoreAsync();
dataWriter.DetachStream();
}
await outputStream.FlushAsync();
}
}
}
}

Categories