SDL Image won't help you in any way when making an NES emu. Also, I don't think OpenGL has anything to offer, either. Just the basic SDL library is really all you need. You won't need/have any textures/surfaces other than the back buffer (your best bet is to redraw the entire screen pixel by pixel every frame, rather than blit 8x8 tiles to the screen.. this way mid-scanline and mid-frame writes can be properly emulated).
I'm not really familiar with OpenAL, but I think the Sound streaming functions in SDL should more than suffice for your needs.
The hardest part about emulating the NES is running the PPU, main CPU, and pAPU all at the same time (as time passes in one of them, time is also passing in the 2 other ones, and you have to keep them all updated). Games often use timing tricks for some visual effects, so you have to manage the 3 areas properly.
In my emu I kept 3 different cycle counters, (one for CPU, PPU, and APU). I based EVERYTHING in PPU cycles (since 1 PPU cycle is a third of a CPU cycle... this avoids having to deal with fractions of cycles). I'd recommend doing something like this (which has worked well for me in the past):
1) Lock the back buffer, hand off the pointer to the buffer to your PPU emu.
2) Run the CPU for a frame.. or until the nearest IRQ (whichever comes first)
--a) whenever the CPU makes a write/read to PPU/APU regs, have the PPU/APU 'catch up' to the current CPU cycle (in the case of the PPU, this means rendering pixels up to the current time, in the APU it means generating sound samples). Also update the PPU on CHR-bank swaps... and update the APU on PRG-bank swaps.
--b) when the CPU strobes the joypads, poll user input (makes it pretty simple ^^)
--c) when the CPU does anything IRQ related, re-evaluate when the next IRQ is going to occur
3) Repeat #2 until a full frame has passed
4) Catch the PPU and APU up to the CPU
5) Unlock back buffer, wait until ~1/60th of a second has passed, then swap the image to the screen (this is probably where you could check for SDL events like exit messages and stuff).
For CPU emulation... a big switch statement is the best way to go. Most if not all compilers will convert a large switch statement to a jump table after it's compiled, and that's really the best you can get (unless maybe you put inline assembly... but that would destroy the portability I'd assume you're going for with SDL).