Post

Replies

Boosts

Views

Activity

AVMIDIPlayer not working for all instruments
Hi, I test AVMIDIPlayer in order to replace classes written based on AVAudioEngine with callbacks functions sending MIDI events to test, I use an NSMutableData filled with: the MIDI header a track for time signature a track containing a few midi events. I then create an instance of the AVMIDIPlayer using the data Everything works fine for some instrument (00 … 20) or 90 but not for other instruments 60, 70, … The MiDI header and the time signature track are based on the MIDI.org sample, https://midi.org/standard-midi-files-specification RP-001_v1-0_Standard_MIDI_Files_Specification_96-1-4.pdf the midi events are: UInt8 trkEvents[] = { 0x00, 0xC0, instrument, // Tubular bell 0x00, 0x90, 0x4C, 0xA0, // Note 4C 0x81, 0x40, 0x48, 0xB0, // TS + Note 48 0x00, 0xFF, 0x2F, 0x00}; // End for (UInt8 i=0; i<3; i++) { printf("0x%X ", trkEvents[i]); } printf("\n"); [_midiTempData appendBytes:trkEvents length:sizeof(trkEvents)]; A template application is used to change the instrument in a NSTextField I was wondering if specifics are required for some instruments? The interface header: #import <AVFoundation/AVFoundation.h> NS_ASSUME_NONNULL_BEGIN @interface TestMIDIPlayer : NSObject @property (retain) NSMutableData *midiTempData; @property (retain) NSURL *midiTempURL; @property (retain) AVMIDIPlayer *midiPlayer; - (void)createTest:(UInt8)instrument; @end NS_ASSUME_NONNULL_END The implementation: #pragma mark - typedef struct _MThd { char magic[4]; // = "MThd" UInt8 headerSize[4]; // 4 Bytes, MSB first. Always = 00 00 00 06 UInt8 format[2]; // 16 bit, MSB first. 0; 1; 2 Use 1 UInt8 trackCount[2]; // 16 bit, MSB first. UInt8 division[2]; // }MThd; MThd MThdMake(void); void MThdPrint(MThd *mthd) ; typedef struct _MIDITrackHeader { char magic[4]; // = "MTrk" UInt8 trackLength[4]; // Ignore, because it is occasionally wrong. } Track; Track TrackMake(void); void TrackPrint(Track *track) ; #pragma mark - C Functions MThd MThdMake(void) { MThd mthd = { "MThd", {0, 0, 0, 6}, {0, 1}, {0, 0}, {0, 0} }; MThdPrint(&mthd); return mthd; } void MThdPrint(MThd *mthd) { char *ptr = (char *)mthd; for (int i=0;i<sizeof(MThd); i++, ptr++) { printf("%X", *ptr); } printf("\n"); } Track TrackMake(void) { Track track = { "MTrk", {0, 0, 0, 0} }; TrackPrint(&track); return track; } void TrackPrint(Track *track) { char *ptr = (char *)track; for (int i=0;i<sizeof(Track); i++, ptr++) { printf("%X", *ptr); } printf("\n"); } @implementation TestMIDIPlayer - (id)init { self = [super init]; printf("%s %p\n", __FUNCTION__, self); if (self) { _midiTempData = nil; _midiTempURL = [[NSURL alloc]initFileURLWithPath:@"midiTempUrl.mid"]; _midiPlayer = nil; [self createTest:0x0E]; NSLog(@"_midiTempData:%@", _midiTempData); } return self; } - (void)dealloc { [_midiTempData release]; [_midiTempURL release]; [_midiPlayer release]; [super dealloc]; } - (void)createTest:(UInt8)instrument { /* MIDI Header */ [_midiTempData release]; _midiTempData = nil; _midiTempData = [[NSMutableData alloc]initWithCapacity:1024]; MThd mthd = MThdMake(); MThd *ptrMthd = &mthd; ptrMthd->trackCount[1] = 2; ptrMthd->division[1] = 0x60; MThdPrint(ptrMthd); [_midiTempData appendBytes:ptrMthd length:sizeof(MThd)]; /* Track Header Time signature */ Track track = TrackMake(); Track *ptrTrack = &track; ptrTrack->trackLength[3] = 0x14; [_midiTempData appendBytes:ptrTrack length:sizeof(track)]; UInt8 trkEventsTS[]= { 0x00, 0xFF, 0x58, 0x04, 0x04, 0x04, 0x18, 0x08, // Time signature 4/4; 18; 08 0x00, 0xFF, 0x51, 0x03, 0x07, 0xA1, 0x20, // tempo 0x7A120 = 500000 0x83, 0x00, 0xFF, 0x2F, 0x00 }; // End [_midiTempData appendBytes:trkEventsTS length:sizeof(trkEventsTS)]; /* Track Header Track events */ ptrTrack->trackLength[3] = 0x0F; [_midiTempData appendBytes:ptrTrack length:sizeof(track)]; UInt8 trkEvents[] = { 0x00, 0xC0, instrument, // Tubular bell 0x00, 0x90, 0x4C, 0xA0, // Note 4C 0x81, 0x40, 0x48, 0xB0, // TS + Note 48 0x00, 0xFF, 0x2F, 0x00}; // End for (UInt8 i=0; i<3; i++) { printf("0x%X ", trkEvents[i]); } printf("\n"); [_midiTempData appendBytes:trkEvents length:sizeof(trkEvents)]; [_midiTempData writeToURL:_midiTempURL atomically:YES]; dispatch_async(dispatch_get_main_queue(), ^{ if (!_midiPlayer.isPlaying) [self midiPlay]; }); } - (void)midiPlay { NSError *error = nil; _midiPlayer = [[AVMIDIPlayer alloc]initWithData:_midiTempData soundBankURL:nil error:&error]; if (_midiPlayer) { [_midiPlayer prepareToPlay]; [_midiPlayer play:^{ printf("Midi Player ended\n"); [_midiPlayer stop]; [_midiPlayer release]; _midiPlayer = nil; }]; } } @end Call from AppDelegate - (IBAction)actionInstrument:(NSTextField*)sender { [_testMidiplayer createTest:(UInt8)sender.intValue]; }
1
0
258
Nov ’24
SwiftUI List OutlineGroup
Hello, I'm having some difficulties trying to customise a SwiftUI list-detail splitview using List and OutlineGroup: The model used is provided in Apple documentation OutlineGroup. The contentView is struct ContentView: View { @State var itemString = String() var body: some View { HSplitView { MyOutLine(title: "MyOutLine", itemString: $itemString) .frame(width: 200, height: 300 , alignment: Alignment(horizontal: .leading, vertical: .top)) .padding() MyView(itemString: itemString) } } } The left view is struct MyOutLine: View { let title:String @Binding var itemString:String @State private var selection: FileItem? var body: some View { List(selection: $selection) { OutlineGroup(data, children: \.children) { item in Text ("\(item.description)") .onTapGesture { selection = item itemString = item.description } .listRowBackground( selection == item ? Color.gray :nil ) } } .listStyle(.sidebar) .onAppear { itemString = "No selection"} } } The right view is: struct MyView: View { let itemString:String var body: some View { VStack{ Spacer() HStack { Spacer() Text(itemString) Spacer() } Spacer() } } } The result works but I have 2 problems: The selection works but the detail view is updated only when I click the text but not when I click the rest of the row. This results in the detail view not being sync with the list selection. I would like to customise the colour of the selected row but listRowBackground does not seem to work. Is there a way to fix this Thank you in advance Jean Marie
2
0
574
Jul ’24
sem_t in sandbox app
Hello, For educational purpose, I try to use a POSIX semaphore sem_t instead of a dispatch_semaphore_t in a sandbox macOS Obj-C app. When using sandbox, the semaphore code creation : sem_t * _unixSemaphore; char nameSemaphore[64] = {0}; snprintf(nameSemaphore, 22, "/UnixSemaphore_sample"); _unixSemaphore = sem_open(nameSemaphore, O_CREAT, 0644, 0); fails, receiving SEM_FAILED and the errno is 78 (not implemented) However, the sem_t _unixSemaphore is created and works fine when I disable sandbox I my entitlements. Is there a way to fix this? Thank you in advance Jean Marie
4
0
672
Jun ’24
Apple TV 3 dead or standby?
Hi, I just notice a few days after having to setup for a new Box TV received from the TV and Internet provider, that my Apple TV does not work anymore. The led is off and the HDMI port connected to the AppleTV is not shown on the TV configuration. I'm convinced that there was somehow a current failure during the setup of my new box TV. I change the HDMI cable but without success Question: How to make sure that the Apple TV is dead or simply in standby. In the late, how to restart it Many thank Jean
1
0
1.1k
Dec ’22
Swift CPU usage for-loop
Hi, I migrate an audio project using AVAudioEngine from Objective-C to Swift.  All objects  are the same but in Swift instead of Objective-C. The application uses the microphone input and analyses it via a renderCallback process calling the FFT  of the Accelerate framework. The session has an important CPU usage:  - TheObjective-C version keeps the CPU usage at 8%  - The  Swift version is on average at 20%. I have isolated the code that  originates the increase and it is due to a method analysing the returned samples in order to summarize them. Parameters: arrMagCount = 12 arrMag is an array of float containing the magnitude of the frequency range related to the index samplesCount = 4096 samples is a pointer of a float array delivering the magnitude of each bins used Result:  Each arrMag[index] is updated with the magnitude related to the range of frequency underlying the index The Objective-C version calls a C process for the  function The Swift version was developped in swift since we cannot mix C code and Swift code in the same source     func arrMagFill(arrMagCount:Int, samplesCount:Int, samples:UnsafePointer<Double>, arrMag:UnsafeMutablePointer<Float>, maxFrequency:CGFloat) {         // Zeroes arrMag.         memset(arrMag, 0, arrMagCount)         for iBin in 0..<samplesCount {             for iLoop in 0..<arrMagCount {                 if maxFrequency  <  g.FreqMetersRangeMaxValue[iLoop] {                     arrMag[iLoop] = Float(samples[Int(iBin)])                     break                 }             }         }     } When I use a C equivalent code via an Objective-C  bridge Header, the CPU usage is back to [8..12] on average. Is there a way in Swift to obtain directly the same performances ?
2
0
921
Jun ’22